Fixed smbClose() for older dkppc versions
[libogc.git] / lwip / network.c
blobd0b19c171cb1d6998bdd29a8510cbe1552dd5660
1 #include <time.h>
2 #include <errno.h>
3 #include <unistd.h>
4 #include <ogcsys.h>
5 #include <lwp.h>
6 #include <video.h>
7 #include <message.h>
8 #include <mutex.h>
9 #include <cond.h>
10 #include <semaphore.h>
11 #include <processor.h>
12 #include <lwp_threads.h>
13 #include <lwp_watchdog.h>
14 #include <lwip/debug.h>
15 #include <lwip/opt.h>
16 #include <lwip/mem.h>
17 #include <lwip/memp.h>
18 #include <lwip/sys.h>
19 #include <lwip/stats.h>
20 #include <lwip/ip.h>
21 #include <lwip/raw.h>
22 #include <lwip/udp.h>
23 #include <lwip/tcp.h>
24 #include <lwip/dhcp.h>
25 #include <lwip/api.h>
26 #include <lwip/api_msg.h>
27 #include <lwip/tcpip.h>
28 #include <netif/etharp.h>
29 #include <netif/loopif.h>
30 #include <netif/gcif/gcif.h>
32 #include <sys/iosupport.h>
34 #include "network.h"
36 //#define _NET_DEBUG
37 #define ARP_TIMER_ID 0x00070041
38 #define TCP_TIMER_ID 0x00070042
39 #define DHCPCOARSE_TIMER_ID 0x00070043
40 #define DHCPFINE_TIMER_ID 0x00070044
42 #define STACKSIZE 32768
43 #define MQBOX_SIZE 256
44 #define NUM_SOCKETS MEMP_NUM_NETCONN
46 struct netsocket {
47 struct netconn *conn;
48 struct netbuf *lastdata;
49 u16 lastoffset,rcvevt,sendevt,flags;
50 s32 err;
53 struct netselect_cb {
54 struct netselect_cb *next;
55 fd_set *readset;
56 fd_set *writeset;
57 fd_set *exceptset;
58 u32 signaled;
59 mutex_t cond_lck;
60 cond_t cond;
63 typedef void (*apimsg_decode)(struct apimsg_msg *);
65 static u32 g_netinitiated = 0;
66 static u32 tcpiplayer_inited = 0;
67 static u64 net_tcp_ticks = 0;
68 static u64 net_dhcpcoarse_ticks = 0;
69 static u64 net_dhcpfine_ticks = 0;
70 static u64 net_arp_ticks = 0;
71 static wd_cntrl arp_time_cntrl;
72 static wd_cntrl tcp_timer_cntrl;
73 static wd_cntrl dhcp_coarsetimer_cntrl;
74 static wd_cntrl dhcp_finetimer_cntrl;
76 static struct netif g_hNetIF;
77 static struct netif g_hLoopIF;
78 static struct netsocket sockets[NUM_SOCKETS];
79 static struct netselect_cb *selectcb_list = NULL;
81 static sys_sem netsocket_sem;
82 static sys_sem sockselect_sem;
83 static sys_mbox netthread_mbox;
85 static sys_thread hnet_thread;
86 static u8 netthread_stack[STACKSIZE];
88 static u32 tcp_timer_active = 0;
90 static struct netbuf* netbuf_new();
91 static void netbuf_delete(struct netbuf *);
92 static void netbuf_copypartial(struct netbuf *,void *,u32,u32);
93 static void netbuf_ref(struct netbuf *,const void *,u32);
95 static struct netconn* netconn_new_with_callback(enum netconn_type,void (*)(struct netconn *,enum netconn_evt,u32));
96 static struct netconn* netconn_new_with_proto_and_callback(enum netconn_type,u16,void (*)(struct netconn *,enum netconn_evt,u32));
97 static err_t netconn_delete(struct netconn *);
98 static struct netconn* netconn_accept(struct netconn* );
99 static err_t netconn_peer(struct netconn *,struct ip_addr *,u16 *);
100 static err_t netconn_bind(struct netconn *,struct ip_addr *,u16);
101 static err_t netconn_listen(struct netconn *);
102 static struct netbuf* netconn_recv(struct netconn *);
103 static err_t netconn_send(struct netconn *,struct netbuf *);
104 static err_t netconn_write(struct netconn *,const void *,u32,u8);
105 static err_t netconn_connect(struct netconn *,struct ip_addr *,u16);
106 static err_t netconn_disconnect(struct netconn *);
108 static void do_newconn(struct apimsg_msg *);
109 static void do_delconn(struct apimsg_msg *);
110 static void do_bind(struct apimsg_msg *);
111 static void do_listen(struct apimsg_msg *);
112 static void do_connect(struct apimsg_msg *);
113 static void do_disconnect(struct apimsg_msg *);
114 static void do_accept(struct apimsg_msg *);
115 static void do_send(struct apimsg_msg *);
116 static void do_recv(struct apimsg_msg *);
117 static void do_write(struct apimsg_msg *);
118 static void do_close(struct apimsg_msg *);
120 static apimsg_decode decode[APIMSG_MAX] = {
121 do_newconn,
122 do_delconn,
123 do_bind,
124 do_connect,
125 do_disconnect,
126 do_listen,
127 do_accept,
128 do_send,
129 do_recv,
130 do_write,
131 do_close
134 static void apimsg_post(struct api_msg *);
136 static err_t net_input(struct pbuf *,struct netif *);
137 static void net_apimsg(struct api_msg *);
138 static err_t net_callback(void (*)(void *),void *);
139 static void* net_thread(void *);
141 static void tmr_callback(void *arg)
143 void (*functor)() = (void(*)())arg;
144 if(functor) functor();
147 /* low level stuff */
148 static void __dhcpcoarse_timer(void *arg)
150 __lwp_thread_dispatchdisable();
151 net_callback(tmr_callback,(void*)dhcp_coarse_tmr);
152 __lwp_wd_insert_ticks(&dhcp_coarsetimer_cntrl,net_dhcpcoarse_ticks);
153 __lwp_thread_dispatchunnest();
156 static void __dhcpfine_timer(void *arg)
158 __lwp_thread_dispatchdisable();
159 net_callback(tmr_callback,(void*)dhcp_fine_tmr);
160 __lwp_wd_insert_ticks(&dhcp_finetimer_cntrl,net_dhcpfine_ticks);
161 __lwp_thread_dispatchunnest();
164 static void __tcp_timer(void *arg)
166 #ifdef _NET_DEBUG
167 printf("__tcp_timer(%d,%p,%p)\n",tcp_timer_active,tcp_active_pcbs,tcp_tw_pcbs);
168 #endif
169 __lwp_thread_dispatchdisable();
170 net_callback(tmr_callback,(void*)tcp_tmr);
171 if (tcp_active_pcbs || tcp_tw_pcbs) {
172 __lwp_wd_insert_ticks(&tcp_timer_cntrl,net_tcp_ticks);
173 } else
174 tcp_timer_active = 0;
175 __lwp_thread_dispatchunnest();
178 static void __arp_timer(void *arg)
180 __lwp_thread_dispatchdisable();
181 net_callback(tmr_callback,(void*)etharp_tmr);
182 __lwp_wd_insert_ticks(&arp_time_cntrl,net_arp_ticks);
183 __lwp_thread_dispatchunnest();
186 void tcp_timer_needed(void)
188 #ifdef _NET_DEBUG
189 printf("tcp_timer_needed()\n");
190 #endif
191 if(!tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
192 tcp_timer_active = 1;
193 __lwp_wd_insert_ticks(&tcp_timer_cntrl,net_tcp_ticks);
197 /* netbuf part */
198 static __inline__ u16 netbuf_len(struct netbuf *buf)
200 return ((buf && buf->p)?buf->p->tot_len:0);
203 static __inline__ struct ip_addr* netbuf_fromaddr(struct netbuf *buf)
205 return (buf?buf->fromaddr:NULL);
208 static __inline__ u16 netbuf_fromport(struct netbuf *buf)
210 return (buf?buf->fromport:0);
213 static void netbuf_copypartial(struct netbuf *buf,void *dataptr,u32 len,u32 offset)
215 struct pbuf *p;
216 u16 i,left;
218 left = 0;
219 if(buf==NULL || dataptr==NULL) return;
221 for(p=buf->p;left<len && p!=NULL;p=p->next) {
222 if(offset!=0 && offset>=p->len)
223 offset -= p->len;
224 else {
225 for(i=offset;i<p->len;i++) {
226 ((u8*)dataptr)[left] = ((u8*)p->payload)[i];
227 if(++left>=len) return;
229 offset = 0;
234 static struct netbuf* netbuf_new()
236 struct netbuf *buf = NULL;
238 buf = memp_malloc(MEMP_NETBUF);
239 if(buf) {
240 buf->p = NULL;
241 buf->ptr = NULL;
243 return buf;
246 static void netbuf_delete(struct netbuf *buf)
248 if(buf!=NULL) {
249 if(buf->p!=NULL) pbuf_free(buf->p);
250 memp_free(MEMP_NETBUF,buf);
254 static void netbuf_ref(struct netbuf *buf, const void *dataptr,u32 size)
256 if(buf->p!=NULL) pbuf_free(buf->p);
257 buf->p = pbuf_alloc(PBUF_TRANSPORT,0,PBUF_REF);
258 buf->p->payload = (void*)dataptr;
259 buf->p->len = buf->p->tot_len = size;
260 buf->ptr = buf->p;
263 /* netconn part */
264 static inline enum netconn_type netconn_type(struct netconn *conn)
266 return conn->type;
269 static struct netconn* netconn_new_with_callback(enum netconn_type t,void (*cb)(struct netconn*,enum netconn_evt,u32))
271 return netconn_new_with_proto_and_callback(t,0,cb);
274 static struct netconn* netconn_new_with_proto_and_callback(enum netconn_type t,u16 proto,void (*cb)(struct netconn *,enum netconn_evt,u32))
276 u32 dummy = 0;
277 struct netconn *conn;
278 struct api_msg *msg;
280 conn = memp_malloc(MEMP_NETCONN);
281 if(!conn) return NULL;
283 conn->err = ERR_OK;
284 conn->type = t;
285 conn->pcb.tcp = NULL;
287 if(MQ_Init(&conn->mbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) {
288 memp_free(MEMP_NETCONN,conn);
289 return NULL;
291 if(LWP_SemInit(&conn->sem,0,1)==-1) {
292 MQ_Close(conn->mbox);
293 memp_free(MEMP_NETCONN,conn);
294 return NULL;
297 conn->acceptmbox = SYS_MBOX_NULL;
298 conn->recvmbox = SYS_MBOX_NULL;
299 conn->state = NETCONN_NONE;
300 conn->socket = 0;
301 conn->callback = cb;
302 conn->recvavail = 0;
304 msg = memp_malloc(MEMP_API_MSG);
305 if(!msg) {
306 MQ_Close(conn->mbox);
307 memp_free(MEMP_NETCONN,conn);
308 return NULL;
311 msg->type = APIMSG_NEWCONN;
312 msg->msg.msg.bc.port = proto;
313 msg->msg.conn = conn;
314 apimsg_post(msg);
315 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
316 memp_free(MEMP_API_MSG,msg);
318 if(conn->err!=ERR_OK) {
319 MQ_Close(conn->mbox);
320 memp_free(MEMP_NETCONN,conn);
321 return NULL;
323 return conn;
326 static err_t netconn_delete(struct netconn *conn)
328 u32 dummy = 0;
329 struct api_msg *msg;
330 sys_mbox mbox;
331 void *mem;
333 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_delete(%p)\n", conn));
335 if(!conn) return ERR_OK;
337 msg = memp_malloc(MEMP_API_MSG);
338 if(!msg) return ERR_MEM;
340 msg->type = APIMSG_DELCONN;
341 msg->msg.conn = conn;
342 apimsg_post(msg);
343 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
344 memp_free(MEMP_API_MSG,msg);
346 mbox = conn->recvmbox;
347 conn->recvmbox = SYS_MBOX_NULL;
348 if(mbox!=SYS_MBOX_NULL) {
349 while(MQ_Receive(mbox,(mqmsg_t)&mem,MQ_MSG_NOBLOCK)==TRUE) {
350 if(mem!=NULL) {
351 if(conn->type==NETCONN_TCP)
352 pbuf_free((struct pbuf*)mem);
353 else
354 netbuf_delete((struct netbuf*)mem);
357 MQ_Close(mbox);
360 mbox = conn->acceptmbox;
361 conn->acceptmbox = SYS_MBOX_NULL;
362 if(mbox!=SYS_MBOX_NULL) {
363 while(MQ_Receive(mbox,(mqmsg_t)&mem,MQ_MSG_NOBLOCK)==TRUE) {
364 if(mem!=NULL) netconn_delete((struct netconn*)mem);
366 MQ_Close(mbox);
369 MQ_Close(conn->mbox);
370 conn->mbox = SYS_MBOX_NULL;
372 LWP_SemDestroy(conn->sem);
373 conn->sem = SYS_SEM_NULL;
375 memp_free(MEMP_NETCONN,conn);
376 return ERR_OK;
379 static struct netconn* netconn_accept(struct netconn* conn)
381 struct netconn *newconn;
383 if(conn==NULL) return NULL;
385 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_accept(%p)\n", conn));
386 MQ_Receive(conn->acceptmbox,(mqmsg_t)&newconn,MQ_MSG_BLOCK);
387 if(conn->callback)
388 (*conn->callback)(conn,NETCONN_EVTRCVMINUS,0);
390 return newconn;
393 static err_t netconn_peer(struct netconn *conn,struct ip_addr *addr,u16 *port)
395 switch(conn->type) {
396 case NETCONN_RAW:
397 return ERR_CONN;
398 case NETCONN_UDPLITE:
399 case NETCONN_UDPNOCHKSUM:
400 case NETCONN_UDP:
401 if(conn->pcb.udp==NULL || ((conn->pcb.udp->flags&UDP_FLAGS_CONNECTED)==0))
402 return ERR_CONN;
403 *addr = conn->pcb.udp->remote_ip;
404 *port = conn->pcb.udp->remote_port;
405 break;
406 case NETCONN_TCP:
407 if(conn->pcb.tcp==NULL)
408 return ERR_CONN;
409 *addr = conn->pcb.tcp->remote_ip;
410 *port = conn->pcb.tcp->remote_port;
411 break;
413 return (conn->err = ERR_OK);
416 static err_t netconn_bind(struct netconn *conn,struct ip_addr *addr,u16 port)
418 u32 dummy = 0;
419 struct api_msg *msg;
421 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_bind(%p)\n", conn));
423 if(conn==NULL) return ERR_VAL;
424 if(conn->type!=NETCONN_TCP && conn->recvmbox==SYS_MBOX_NULL) {
425 if(MQ_Init(&conn->recvmbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) return ERR_MEM;
428 if((msg=memp_malloc(MEMP_API_MSG))==NULL)
429 return (conn->err = ERR_MEM);
431 msg->type = APIMSG_BIND;
432 msg->msg.conn = conn;
433 msg->msg.msg.bc.ipaddr = addr;
434 msg->msg.msg.bc.port = port;
435 apimsg_post(msg);
436 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
437 memp_free(MEMP_API_MSG,msg);
438 return conn->err;
441 static err_t netconn_listen(struct netconn *conn)
443 u32 dummy = 0;
444 struct api_msg *msg;
446 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_listen(%p)\n", conn));
448 if(conn==NULL) return -1;
449 if(conn->acceptmbox==SYS_MBOX_NULL) {
450 if(MQ_Init(&conn->acceptmbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) return ERR_MEM;
453 if((msg=memp_malloc(MEMP_API_MSG))==NULL) return (conn->err = ERR_MEM);
454 msg->type = APIMSG_LISTEN;
455 msg->msg.conn = conn;
456 apimsg_post(msg);
457 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
458 memp_free(MEMP_API_MSG,msg);
459 return conn->err;
462 static struct netbuf* netconn_recv(struct netconn *conn)
464 u32 dummy = 0;
465 struct api_msg *msg;
466 struct netbuf *buf;
467 struct pbuf *p;
468 u16 len;
470 if(conn==NULL) return NULL;
471 if(conn->recvmbox==SYS_MBOX_NULL) {
472 conn->err = ERR_CONN;
473 return NULL;
475 if(conn->err!=ERR_OK) return NULL;
477 if(conn->type==NETCONN_TCP) {
478 if(conn->pcb.tcp->state==LISTEN) {
479 conn->err = ERR_CONN;
480 return NULL;
483 buf = memp_malloc(MEMP_NETBUF);
484 if(buf==NULL) {
485 conn->err = ERR_MEM;
486 return NULL;
489 MQ_Receive(conn->recvmbox,(mqmsg_t)&p,MQ_MSG_BLOCK);
490 if(p!=NULL) {
491 len = p->tot_len;
492 conn->recvavail -= len;
493 } else
494 len = 0;
496 if(conn->callback)
497 (*conn->callback)(conn,NETCONN_EVTRCVMINUS,len);
499 if(p==NULL) {
500 memp_free(MEMP_NETBUF,buf);
501 MQ_Close(conn->recvmbox);
502 conn->recvmbox = SYS_MBOX_NULL;
503 return NULL;
506 buf->p = p;
507 buf->ptr = p;
508 buf->fromport = 0;
509 buf->fromaddr = NULL;
511 if((msg=memp_malloc(MEMP_API_MSG))==NULL) {
512 conn->err = ERR_MEM;
513 return buf;
516 msg->type = APIMSG_RECV;
517 msg->msg.conn = conn;
518 if(buf!=NULL)
519 msg->msg.msg.len = len;
520 else
521 msg->msg.msg.len = 1;
523 apimsg_post(msg);
524 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
525 memp_free(MEMP_API_MSG,msg);
526 } else {
527 MQ_Receive(conn->recvmbox,(mqmsg_t)&buf,MQ_MSG_BLOCK);
528 conn->recvavail -= buf->p->tot_len;
529 if(conn->callback)
530 (*conn->callback)(conn,NETCONN_EVTRCVMINUS,buf->p->tot_len);
533 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void *)buf, conn->err));
534 return buf;
537 static err_t netconn_send(struct netconn *conn,struct netbuf *buf)
539 u32 dummy = 0;
540 struct api_msg *msg;
542 if(conn==NULL) return ERR_VAL;
543 if(conn->err!=ERR_OK) return conn->err;
544 if((msg=memp_malloc(MEMP_API_MSG))==NULL) return (conn->err = ERR_MEM);
546 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
547 msg->type = APIMSG_SEND;
548 msg->msg.conn = conn;
549 msg->msg.msg.p = buf->p;
550 apimsg_post(msg);
551 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
552 memp_free(MEMP_API_MSG,msg);
553 return conn->err;
556 static err_t netconn_write(struct netconn *conn,const void *dataptr,u32 size,u8 copy)
558 u32 dummy = 0;
559 struct api_msg *msg;
560 u16 len,snd_buf;
563 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write(%d)\n",conn->err));
565 if(conn==NULL) return ERR_VAL;
566 if(conn->err!=ERR_OK) return conn->err;
568 if((msg=memp_malloc(MEMP_API_MSG))==NULL) return (conn->err = ERR_MEM);
570 msg->type = APIMSG_WRITE;
571 msg->msg.conn = conn;
572 conn->state = NETCONN_WRITE;
573 while(conn->err==ERR_OK && size>0) {
574 msg->msg.msg.w.dataptr = (void*)dataptr;
575 msg->msg.msg.w.copy = copy;
576 if(conn->type==NETCONN_TCP) {
577 while((snd_buf=tcp_sndbuf(conn->pcb.tcp))==0) {
578 LWIP_DEBUGF(API_LIB_DEBUG,("netconn_write: tcp_sndbuf = 0,err = %d\n", conn->err));
579 LWP_SemWait(conn->sem);
580 if(conn->err!=ERR_OK) goto ret;
582 if(size>snd_buf)
583 len = snd_buf;
584 else
585 len = size;
586 } else
587 len = size;
589 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
590 msg->msg.msg.w.len = len;
591 apimsg_post(msg);
592 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
593 if(conn->err==ERR_OK) {
594 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: %d bytes written\n",len));
595 dataptr = (void*)((char*)dataptr+len);
596 size -= len;
597 } else if(conn->err==ERR_MEM) {
598 LWIP_DEBUGF(API_LIB_DEBUG,("netconn_write: mem err\n"));
599 conn->err = ERR_OK;
600 LWP_SemWait(conn->sem);
601 } else {
602 LWIP_DEBUGF(API_LIB_DEBUG,("netconn_write: err = %d\n", conn->err));
603 break;
606 ret:
607 memp_free(MEMP_API_MSG,msg);
608 conn->state = NETCONN_NONE;
610 return conn->err;
613 static err_t netconn_connect(struct netconn *conn,struct ip_addr *addr,u16 port)
615 u32 dummy = 0;
616 struct api_msg *msg;
618 if(conn==NULL) return -1;
619 if(conn->recvmbox==SYS_MBOX_NULL) {
620 if(MQ_Init(&conn->recvmbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) return ERR_MEM;
623 if((msg=memp_malloc(MEMP_API_MSG))==NULL) return ERR_MEM;
625 msg->type = APIMSG_CONNECT;
626 msg->msg.conn = conn;
627 msg->msg.msg.bc.ipaddr = addr;
628 msg->msg.msg.bc.port = port;
629 apimsg_post(msg);
630 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
631 memp_free(MEMP_API_MSG,msg);
632 return conn->err;
635 static err_t netconn_disconnect(struct netconn *conn)
637 u32 dummy = 0;
638 struct api_msg *msg;
640 if(conn==NULL) return ERR_VAL;
641 if((msg=memp_malloc(MEMP_API_MSG))==NULL) return ERR_MEM;
643 msg->type = APIMSG_DISCONNECT;
644 msg->msg.conn = conn;
645 apimsg_post(msg);
646 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
647 memp_free(MEMP_API_MSG,msg);
648 return conn->err;
651 /* api msg part */
652 static u8_t recv_raw(void *arg,struct raw_pcb *pcb,struct pbuf *p,struct ip_addr *addr)
654 struct netbuf *buf;
655 struct netconn *conn = (struct netconn*)arg;
657 if(!conn) return 0;
659 if(conn->recvmbox!=SYS_MBOX_NULL) {
660 if((buf=memp_malloc(MEMP_NETBUF))==NULL) return 0;
662 pbuf_ref(p);
663 buf->p = p;
664 buf->ptr = p;
665 buf->fromaddr = addr;
666 buf->fromport = pcb->protocol;
668 conn->recvavail += p->tot_len;
669 if(conn->callback)
670 (*conn->callback)(conn,NETCONN_EVTRCVPLUS,p->tot_len);
671 MQ_Send(conn->recvmbox,&buf,MQ_MSG_BLOCK);
673 return 0;
676 static void recv_udp(void *arg,struct udp_pcb *pcb,struct pbuf *p,struct ip_addr *addr,u16 port)
678 struct netbuf *buf;
679 struct netconn *conn = (struct netconn*)arg;
681 if(!conn) {
682 pbuf_free(p);
683 return;
686 if(conn->recvmbox!=SYS_MBOX_NULL) {
687 buf = memp_malloc(MEMP_NETBUF);
688 if(!buf) {
689 pbuf_free(p);
690 return;
692 buf->p = p;
693 buf->ptr = p;
694 buf->fromaddr = addr;
695 buf->fromport = port;
697 conn->recvavail += p->tot_len;
698 if(conn->callback)
699 (*conn->callback)(conn,NETCONN_EVTRCVPLUS,p->tot_len);
701 MQ_Send(conn->recvmbox,&buf,MQ_MSG_BLOCK);
705 static err_t recv_tcp(void *arg,struct tcp_pcb *pcb,struct pbuf *p,err_t err)
707 u16 len;
708 struct netconn *conn = (struct netconn*)arg;
710 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: recv_tcp(%p,%p,%p,%d)\n",arg,pcb,p,err));
712 if(conn==NULL) {
713 pbuf_free(p);
714 return ERR_VAL;
717 if(conn->recvmbox!=SYS_MBOX_NULL) {
718 conn->err = err;
719 if(p!=NULL) {
720 len = p->tot_len;
721 conn->recvavail += len;
722 } else len = 0;
724 if(conn->callback)
725 (*conn->callback)(conn,NETCONN_EVTRCVPLUS,len);
727 MQ_Send(conn->recvmbox,&p,MQ_MSG_BLOCK);
729 return ERR_OK;
732 static void err_tcp(void *arg,err_t err)
734 u32 dummy = 0;
735 struct netconn *conn = (struct netconn*)arg;
737 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: err_tcp: %d\n",err));
738 if(conn) {
739 conn->err = err;
740 conn->pcb.tcp = NULL;
741 if(conn->recvmbox!=SYS_MBOX_NULL) {
742 if(conn->callback) (*conn->callback)(conn,NETCONN_EVTRCVPLUS,0);
743 MQ_Send(conn->recvmbox,&dummy,MQ_MSG_BLOCK);
745 if(conn->mbox!=SYS_MBOX_NULL) {
746 MQ_Send(conn->mbox,&dummy,MQ_MSG_BLOCK);
748 if(conn->acceptmbox!=SYS_MBOX_NULL) {
749 if(conn->callback) (*conn->callback)(conn,NETCONN_EVTRCVPLUS,0);
750 MQ_Send(conn->acceptmbox,&dummy,MQ_MSG_BLOCK);
752 if(conn->sem!=SYS_SEM_NULL) {
753 LWP_SemPost(conn->sem);
758 static err_t poll_tcp(void *arg,struct tcp_pcb *pcb)
760 struct netconn *conn = (struct netconn*)arg;
762 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: poll_tcp\n"));
763 if(conn && conn->sem!=SYS_SEM_NULL && (conn->state==NETCONN_WRITE || conn->state==NETCONN_CLOSE))
764 LWP_SemPost(conn->sem);
766 return ERR_OK;
769 static err_t sent_tcp(void *arg,struct tcp_pcb *pcb,u16 len)
771 struct netconn *conn = (struct netconn*)arg;
773 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: sent_tcp: sent %d bytes\n",len));
774 if(conn && conn->sem!=SYS_SEM_NULL)
775 LWP_SemPost(conn->sem);
777 if(conn && conn->callback) {
778 if(tcp_sndbuf(conn->pcb.tcp)>TCP_SNDLOWAT)
779 (*conn->callback)(conn,NETCONN_EVTSENDPLUS,len);
781 return ERR_OK;
784 static void setuptcp(struct netconn *conn)
786 struct tcp_pcb *pcb = conn->pcb.tcp;
788 tcp_arg(pcb,conn);
789 tcp_recv(pcb,recv_tcp);
790 tcp_sent(pcb,sent_tcp);
791 tcp_poll(pcb,poll_tcp,4);
792 tcp_err(pcb,err_tcp);
795 static err_t accept_func(void *arg,struct tcp_pcb *newpcb,err_t err)
797 sys_mbox mbox;
798 struct netconn *newconn,*conn = (struct netconn*)arg;
800 LWIP_DEBUGF(API_LIB_DEBUG, ("accept_func: %p %p %d\n",arg,newpcb,err));
802 mbox = conn->acceptmbox;
803 newconn = memp_malloc(MEMP_NETCONN);
804 if(newconn==NULL) return ERR_MEM;
806 if(MQ_Init(&newconn->recvmbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) {
807 memp_free(MEMP_NETCONN,newconn);
808 return ERR_MEM;
811 if(MQ_Init(&newconn->mbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) {
812 MQ_Close(newconn->recvmbox);
813 memp_free(MEMP_NETCONN,newconn);
814 return ERR_MEM;
817 if(LWP_SemInit(&newconn->sem,0,1)==-1) {
818 MQ_Close(newconn->recvmbox);
819 MQ_Close(newconn->mbox);
820 memp_free(MEMP_NETCONN,newconn);
821 return ERR_MEM;
824 newconn->type = NETCONN_TCP;
825 newconn->pcb.tcp = newpcb;
826 setuptcp(newconn);
828 newconn->acceptmbox = SYS_MBOX_NULL;
829 newconn->err = err;
831 if(conn->callback) {
832 (*conn->callback)(conn,NETCONN_EVTRCVPLUS,0);
834 newconn->callback = conn->callback;
835 newconn->socket = -1;
836 newconn->recvavail = 0;
838 MQ_Send(mbox,&newconn,MQ_MSG_BLOCK);
839 return ERR_OK;
842 static void do_newconn(struct apimsg_msg *msg)
844 u32 dummy = 0;
846 if(msg->conn->pcb.tcp) {
847 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
848 return;
851 msg->conn->err = ERR_OK;
852 switch(msg->conn->type) {
853 case NETCONN_RAW:
854 msg->conn->pcb.raw = raw_new(msg->msg.bc.port);
855 raw_recv(msg->conn->pcb.raw,recv_raw,msg->conn);
856 break;
857 case NETCONN_UDPLITE:
858 msg->conn->pcb.udp = udp_new();
859 if(!msg->conn->pcb.udp) {
860 msg->conn->err = ERR_MEM;
861 break;
863 udp_setflags(msg->conn->pcb.udp,UDP_FLAGS_UDPLITE);
864 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
865 break;
866 case NETCONN_UDPNOCHKSUM:
867 msg->conn->pcb.udp = udp_new();
868 if(!msg->conn->pcb.udp) {
869 msg->conn->err = ERR_MEM;
870 break;
872 udp_setflags(msg->conn->pcb.udp,UDP_FLAGS_NOCHKSUM);
873 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
874 break;
875 case NETCONN_UDP:
876 msg->conn->pcb.udp = udp_new();
877 if(!msg->conn->pcb.udp) {
878 msg->conn->err = ERR_MEM;
879 break;
881 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
882 break;
883 case NETCONN_TCP:
884 msg->conn->pcb.tcp = tcp_new();
885 if(!msg->conn->pcb.tcp) {
886 msg->conn->err = ERR_MEM;
887 break;
889 setuptcp(msg->conn);
890 break;
891 default:
892 break;
894 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
897 static void do_delconn(struct apimsg_msg *msg)
899 u32 dummy = 0;
901 if(msg->conn->pcb.tcp) {
902 switch(msg->conn->type) {
903 case NETCONN_RAW:
904 raw_remove(msg->conn->pcb.raw);
905 break;
906 case NETCONN_UDPLITE:
907 case NETCONN_UDPNOCHKSUM:
908 case NETCONN_UDP:
909 msg->conn->pcb.udp->recv_arg = NULL;
910 udp_remove(msg->conn->pcb.udp);
911 break;
912 case NETCONN_TCP:
913 if(msg->conn->pcb.tcp->state==LISTEN) {
914 tcp_arg(msg->conn->pcb.tcp,NULL);
915 tcp_accept(msg->conn->pcb.tcp,NULL);
916 tcp_close(msg->conn->pcb.tcp);
917 } else {
918 tcp_arg(msg->conn->pcb.tcp,NULL);
919 tcp_sent(msg->conn->pcb.tcp,NULL);
920 tcp_recv(msg->conn->pcb.tcp,NULL);
921 tcp_poll(msg->conn->pcb.tcp,NULL,0);
922 tcp_err(msg->conn->pcb.tcp,NULL);
923 if(tcp_close(msg->conn->pcb.tcp)!=ERR_OK)
924 tcp_abort(msg->conn->pcb.tcp);
926 break;
927 default:
928 break;
931 if(msg->conn->callback) {
932 (*msg->conn->callback)(msg->conn,NETCONN_EVTRCVPLUS,0);
933 (*msg->conn->callback)(msg->conn,NETCONN_EVTSENDPLUS,0);
935 if(msg->conn->mbox!=SYS_MBOX_NULL)
936 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
939 static void do_bind(struct apimsg_msg *msg)
941 u32 dummy = 0;
943 if(msg->conn->pcb.tcp==NULL) {
944 switch(msg->conn->type) {
945 case NETCONN_RAW:
946 msg->conn->pcb.raw = raw_new(msg->msg.bc.port);
947 raw_recv(msg->conn->pcb.raw,recv_raw,msg->conn);
948 break;
949 case NETCONN_UDPLITE:
950 msg->conn->pcb.udp = udp_new();
951 udp_setflags(msg->conn->pcb.udp,UDP_FLAGS_UDPLITE);
952 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
953 break;
954 case NETCONN_UDPNOCHKSUM:
955 msg->conn->pcb.udp = udp_new();
956 udp_setflags(msg->conn->pcb.udp,UDP_FLAGS_NOCHKSUM);
957 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
958 break;
959 case NETCONN_UDP:
960 msg->conn->pcb.udp = udp_new();
961 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
962 break;
963 case NETCONN_TCP:
964 msg->conn->pcb.tcp = tcp_new();
965 setuptcp(msg->conn);
966 break;
967 default:
968 break;
971 switch(msg->conn->type) {
972 case NETCONN_RAW:
973 msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);
974 break;
975 case NETCONN_UDPLITE:
976 case NETCONN_UDPNOCHKSUM:
977 case NETCONN_UDP:
978 msg->conn->err = udp_bind(msg->conn->pcb.udp,msg->msg.bc.ipaddr,msg->msg.bc.port);
979 break;
980 case NETCONN_TCP:
981 msg->conn->err = tcp_bind(msg->conn->pcb.tcp,msg->msg.bc.ipaddr,msg->msg.bc.port);
982 break;
983 default:
984 break;
986 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
989 static err_t do_connected(void *arg,struct tcp_pcb *pcb,err_t err)
991 u32 dummy = 0;
992 struct netconn *conn = (struct netconn*)arg;
994 if(!conn) return ERR_VAL;
996 conn->err = err;
997 if(conn->type==NETCONN_TCP && err==ERR_OK) setuptcp(conn);
999 MQ_Send(conn->mbox,&dummy,MQ_MSG_BLOCK);
1000 return ERR_OK;
1003 static void do_connect(struct apimsg_msg *msg)
1005 u32 dummy = 0;
1007 if(!msg->conn->pcb.tcp) {
1008 switch(msg->conn->type) {
1009 case NETCONN_RAW:
1010 msg->conn->pcb.raw = raw_new(msg->msg.bc.port);
1011 raw_recv(msg->conn->pcb.raw,recv_raw,msg->conn);
1012 break;
1013 case NETCONN_UDPLITE:
1014 msg->conn->pcb.udp = udp_new();
1015 if(!msg->conn->pcb.udp) {
1016 msg->conn->err = ERR_MEM;
1017 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1018 return;
1020 udp_setflags(msg->conn->pcb.udp,UDP_FLAGS_UDPLITE);
1021 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
1022 break;
1023 case NETCONN_UDPNOCHKSUM:
1024 msg->conn->pcb.udp = udp_new();
1025 if(!msg->conn->pcb.udp) {
1026 msg->conn->err = ERR_MEM;
1027 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1028 return;
1030 udp_setflags(msg->conn->pcb.udp,UDP_FLAGS_NOCHKSUM);
1031 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
1032 break;
1033 case NETCONN_UDP:
1034 msg->conn->pcb.udp = udp_new();
1035 if(!msg->conn->pcb.udp) {
1036 msg->conn->err = ERR_MEM;
1037 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1038 return;
1040 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
1041 break;
1042 case NETCONN_TCP:
1043 msg->conn->pcb.tcp = tcp_new();
1044 if(!msg->conn->pcb.tcp) {
1045 msg->conn->err = ERR_MEM;
1046 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1047 return;
1049 break;
1050 default:
1051 break;
1054 switch(msg->conn->type) {
1055 case NETCONN_RAW:
1056 raw_connect(msg->conn->pcb.raw,msg->msg.bc.ipaddr);
1057 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1058 break;
1059 case NETCONN_UDPLITE:
1060 case NETCONN_UDPNOCHKSUM:
1061 case NETCONN_UDP:
1062 udp_connect(msg->conn->pcb.udp,msg->msg.bc.ipaddr,msg->msg.bc.port);
1063 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1064 break;
1065 case NETCONN_TCP:
1066 setuptcp(msg->conn);
1067 tcp_connect(msg->conn->pcb.tcp,msg->msg.bc.ipaddr,msg->msg.bc.port,do_connected);
1068 break;
1069 default:
1070 break;
1074 static void do_disconnect(struct apimsg_msg *msg)
1076 u32 dummy = 0;
1078 switch(msg->conn->type) {
1079 case NETCONN_RAW:
1080 break;
1081 case NETCONN_UDPLITE:
1082 case NETCONN_UDPNOCHKSUM:
1083 case NETCONN_UDP:
1084 udp_disconnect(msg->conn->pcb.udp);
1085 break;
1086 case NETCONN_TCP:
1087 break;
1089 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1092 static void do_listen(struct apimsg_msg *msg)
1094 u32 dummy = 0;
1096 if(msg->conn->pcb.tcp!=NULL) {
1097 switch(msg->conn->type) {
1098 case NETCONN_RAW:
1099 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n"));
1100 break;
1101 case NETCONN_UDPLITE:
1102 case NETCONN_UDPNOCHKSUM:
1103 case NETCONN_UDP:
1104 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n"));
1105 break;
1106 case NETCONN_TCP:
1107 msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp);
1108 if(msg->conn->pcb.tcp==NULL)
1109 msg->conn->err = ERR_MEM;
1110 else {
1111 if(msg->conn->acceptmbox==SYS_MBOX_NULL) {
1112 if(MQ_Init(&msg->conn->acceptmbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) {
1113 msg->conn->err = ERR_MEM;
1114 break;
1117 tcp_arg(msg->conn->pcb.tcp,msg->conn);
1118 tcp_accept(msg->conn->pcb.tcp,accept_func);
1120 break;
1121 default:
1122 break;
1125 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1128 static void do_accept(struct apimsg_msg *msg)
1130 if(msg->conn->pcb.tcp) {
1131 switch(msg->conn->type) {
1132 case NETCONN_RAW:
1133 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n"));
1134 break;
1135 case NETCONN_UDPLITE:
1136 case NETCONN_UDPNOCHKSUM:
1137 case NETCONN_UDP:
1138 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n"));
1139 break;
1140 case NETCONN_TCP:
1141 break;
1146 static void do_send(struct apimsg_msg *msg)
1148 u32 dummy = 0;
1150 if(msg->conn->pcb.tcp) {
1151 switch(msg->conn->type) {
1152 case NETCONN_RAW:
1153 raw_send(msg->conn->pcb.raw,msg->msg.p);
1154 break;
1155 case NETCONN_UDPLITE:
1156 case NETCONN_UDPNOCHKSUM:
1157 case NETCONN_UDP:
1158 udp_send(msg->conn->pcb.udp,msg->msg.p);
1159 break;
1160 case NETCONN_TCP:
1161 break;
1164 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1167 static void do_recv(struct apimsg_msg *msg)
1169 u32 dummy = 0;
1171 if(msg->conn->pcb.tcp && msg->conn->type==NETCONN_TCP) {
1172 tcp_recved(msg->conn->pcb.tcp,msg->msg.len);
1174 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1177 static void do_write(struct apimsg_msg *msg)
1179 err_t err;
1180 u32 dummy = 0;
1182 if(msg->conn->pcb.tcp) {
1183 switch(msg->conn->type) {
1184 case NETCONN_RAW:
1185 case NETCONN_UDPLITE:
1186 case NETCONN_UDPNOCHKSUM:
1187 case NETCONN_UDP:
1188 msg->conn->err = ERR_VAL;
1189 break;
1190 case NETCONN_TCP:
1191 err = tcp_write(msg->conn->pcb.tcp,msg->msg.w.dataptr,msg->msg.w.len,msg->msg.w.copy);
1192 if(err==ERR_OK && (!msg->conn->pcb.tcp->unacked || (msg->conn->pcb.tcp->flags&TF_NODELAY)
1193 || msg->conn->pcb.tcp->snd_queuelen>1)) {
1194 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: TCP write: tcp_output.\n"));
1195 tcp_output(msg->conn->pcb.tcp);
1197 msg->conn->err = err;
1198 if(msg->conn->callback) {
1199 if(err==ERR_OK) {
1200 if(tcp_sndbuf(msg->conn->pcb.tcp)<=TCP_SNDLOWAT)
1201 (*msg->conn->callback)(msg->conn,NETCONN_EVTSENDMINUS,msg->msg.w.len);
1204 break;
1205 default:
1206 break;
1209 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1212 static void do_close(struct apimsg_msg *msg)
1214 u32 dummy = 0;
1215 err_t err = ERR_OK;
1217 if(msg->conn->pcb.tcp) {
1218 switch(msg->conn->type) {
1219 case NETCONN_RAW:
1220 case NETCONN_UDPLITE:
1221 case NETCONN_UDPNOCHKSUM:
1222 case NETCONN_UDP:
1223 break;
1224 case NETCONN_TCP:
1225 if(msg->conn->pcb.tcp->state==LISTEN)
1226 err = tcp_close(msg->conn->pcb.tcp);
1227 else if(msg->conn->pcb.tcp->state==CLOSE_WAIT)
1228 err = tcp_output(msg->conn->pcb.tcp);
1229 msg->conn->err = err;
1230 break;
1231 default:
1232 break;
1235 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1238 static void apimsg_input(struct api_msg *msg)
1240 decode[msg->type](&(msg->msg));
1243 static void apimsg_post(struct api_msg *msg)
1245 net_apimsg(msg);
1248 /* tcpip thread part */
1249 static err_t net_input(struct pbuf *p,struct netif *inp)
1251 struct net_msg *msg = memp_malloc(MEMP_TCPIP_MSG);
1253 LWIP_DEBUGF(TCPIP_DEBUG, ("net_input: %p %p\n", p,inp));
1255 if(msg==NULL) {
1256 LWIP_ERROR(("net_input: msg out of memory.\n"));
1257 pbuf_free(p);
1258 return ERR_MEM;
1261 msg->type = NETMSG_INPUT;
1262 msg->msg.inp.p = p;
1263 msg->msg.inp.net = inp;
1264 MQ_Send(netthread_mbox,&msg,MQ_MSG_BLOCK);
1265 return ERR_OK;
1268 static void net_apimsg(struct api_msg *apimsg)
1270 struct net_msg *msg = memp_malloc(MEMP_TCPIP_MSG);
1272 LWIP_DEBUGF(TCPIP_DEBUG, ("net_apimsg: %p\n",apimsg));
1273 if(msg==NULL) {
1274 LWIP_ERROR(("net_apimsg: msg out of memory.\n"));
1275 memp_free(MEMP_API_MSG,apimsg);
1276 return;
1279 msg->type = NETMSG_API;
1280 msg->msg.apimsg = apimsg;
1281 MQ_Send(netthread_mbox,&msg,MQ_MSG_BLOCK);
1284 static err_t net_callback(void (*f)(void *),void *ctx)
1286 struct net_msg *msg = memp_malloc(MEMP_TCPIP_MSG);
1288 LWIP_DEBUGF(TCPIP_DEBUG, ("net_callback: %p(%p)\n", f,ctx));
1290 if(msg==NULL) {
1291 LWIP_ERROR(("net_apimsg: msg out of memory.\n"));
1292 return ERR_MEM;
1295 msg->type = NETMSG_CALLBACK;
1296 msg->msg.cb.f = f;
1297 msg->msg.cb.ctx = ctx;
1298 MQ_Send(netthread_mbox,&msg,MQ_MSG_BLOCK);
1299 return ERR_OK;
1302 static void* net_thread(void *arg)
1304 struct net_msg *msg;
1305 struct timespec tb;
1306 sys_sem sem = (sys_sem)arg;
1308 etharp_init();
1309 ip_init();
1310 udp_init();
1311 tcp_init();
1314 tb.tv_sec = ARP_TMR_INTERVAL/TB_MSPERSEC;
1315 tb.tv_nsec = 0;
1316 net_arp_ticks = __lwp_wd_calc_ticks(&tb);
1317 __lwp_wd_initialize(&arp_time_cntrl,__arp_timer,ARP_TIMER_ID,NULL);
1318 __lwp_wd_insert_ticks(&arp_time_cntrl,net_arp_ticks);
1320 tb.tv_sec = 0;
1321 tb.tv_nsec = TCP_TMR_INTERVAL*TB_NSPERMS;
1322 net_tcp_ticks = __lwp_wd_calc_ticks(&tb);
1323 __lwp_wd_initialize(&tcp_timer_cntrl,__tcp_timer,TCP_TIMER_ID,NULL);
1325 LWP_SemPost(sem);
1327 LWIP_DEBUGF(TCPIP_DEBUG, ("net_thread(%p)\n",arg));
1329 while(1) {
1330 MQ_Receive(netthread_mbox,(mqmsg_t)&msg,MQ_MSG_BLOCK);
1331 switch(msg->type) {
1332 case NETMSG_API:
1333 LWIP_DEBUGF(TCPIP_DEBUG, ("net_thread: API message %p\n", (void *)msg));
1334 apimsg_input(msg->msg.apimsg);
1335 break;
1336 case NETMSG_INPUT:
1337 LWIP_DEBUGF(TCPIP_DEBUG, ("net_thread: IP packet %p\n", (void *)msg));
1338 bba_process(msg->msg.inp.p,msg->msg.inp.net);
1339 break;
1340 case NETMSG_CALLBACK:
1341 LWIP_DEBUGF(TCPIP_DEBUG, ("net_thread: CALLBACK %p\n", (void *)msg));
1342 msg->msg.cb.f(msg->msg.cb.ctx);
1343 break;
1344 default:
1345 break;
1347 memp_free(MEMP_TCPIP_MSG,msg);
1349 return NULL;
1352 /* sockets part */
1353 static s32 alloc_socket(struct netconn *conn)
1355 s32 i;
1357 LWP_SemWait(netsocket_sem);
1359 for(i=0;i<NUM_SOCKETS;i++) {
1360 if(!sockets[i].conn) {
1361 sockets[i].conn = conn;
1362 sockets[i].lastdata = NULL;
1363 sockets[i].lastoffset = 0;
1364 sockets[i].rcvevt = 0;
1365 sockets[i].sendevt = 1;
1366 sockets[i].flags = 0;
1367 sockets[i].err = 0;
1368 LWP_SemPost(netsocket_sem);
1369 return i;
1373 LWP_SemPost(netsocket_sem);
1374 return -1;
1377 static struct netsocket* get_socket(s32 s)
1379 struct netsocket *sock;
1380 if(s<0 || s>NUM_SOCKETS) {
1381 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
1382 return NULL;
1384 sock = &sockets[s];
1385 if(!sock->conn) {
1386 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): no active\n", s));
1387 return NULL;
1390 return sock;
1393 static void evt_callback(struct netconn *conn,enum netconn_evt evt,u32 len)
1395 s32 s;
1396 struct netsocket *sock;
1397 struct netselect_cb *scb;
1399 if(conn) {
1400 s = conn->socket;
1401 if(s<0) {
1402 if(evt==NETCONN_EVTRCVPLUS)
1403 conn->socket--;
1404 return;
1406 sock = get_socket(s);
1407 if(!sock) return;
1408 } else
1409 return;
1411 LWP_SemWait(sockselect_sem);
1412 switch(evt) {
1413 case NETCONN_EVTRCVPLUS:
1414 sock->rcvevt++;
1415 break;
1416 case NETCONN_EVTRCVMINUS:
1417 sock->rcvevt--;
1418 break;
1419 case NETCONN_EVTSENDPLUS:
1420 sock->sendevt = 1;
1421 break;
1422 case NETCONN_EVTSENDMINUS:
1423 sock->sendevt = 0;
1424 break;
1426 LWP_SemPost(sockselect_sem);
1428 while(1) {
1429 LWP_SemWait(sockselect_sem);
1430 for(scb = selectcb_list;scb;scb = scb->next) {
1431 if(scb->signaled==0) {
1432 if(scb->readset && FD_ISSET(s,scb->readset))
1433 if(sock->rcvevt) break;
1434 if(scb->writeset && FD_ISSET(s,scb->writeset))
1435 if(sock->sendevt) break;
1438 if(scb) {
1439 scb->signaled = 1;
1440 LWP_SemPost(sockselect_sem);
1441 LWP_MutexLock(scb->cond_lck);
1442 LWP_CondSignal(scb->cond);
1443 LWP_MutexUnlock(scb->cond_lck);
1444 } else {
1445 LWP_SemPost(sockselect_sem);
1446 break;
1452 extern const devoptab_t dotab_stdnet;
1454 s32 if_configex(struct in_addr *local_ip,struct in_addr *netmask,struct in_addr *gateway,boolean use_dhcp)
1456 s32 ret = 0;
1457 struct ip_addr loc_ip, mask, gw;
1458 struct netif *pnet;
1459 struct timespec tb;
1460 dev_s hbba = NULL;
1462 if(g_netinitiated) return 0;
1463 g_netinitiated = 1;
1465 AddDevice(&dotab_stdnet);
1466 #ifdef STATS
1467 stats_init();
1468 #endif /* STATS */
1470 sys_init();
1471 mem_init();
1472 memp_init();
1473 pbuf_init();
1474 netif_init();
1476 // init tcpip thread message box
1477 if(MQ_Init(&netthread_mbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) return -1;
1479 // create & setup interface
1480 loc_ip.addr = 0;
1481 mask.addr = 0;
1482 gw.addr = 0;
1485 if(use_dhcp==FALSE) {
1486 if( !gateway || gateway->s_addr==0
1487 || !local_ip || local_ip->s_addr==0
1488 || !netmask || netmask->s_addr==0 ) return -1;
1489 loc_ip.addr = local_ip->s_addr;
1490 mask.addr = netmask->s_addr;
1491 gw.addr = gateway->s_addr;
1493 hbba = bba_create(&g_hNetIF);
1494 pnet = netif_add(&g_hNetIF,&loc_ip, &mask, &gw, hbba, bba_init, net_input);
1495 if(pnet) {
1496 netif_set_up(pnet);
1497 netif_set_default(pnet);
1498 #if (LWIP_DHCP)
1499 if(use_dhcp==TRUE) {
1500 //setup coarse timer
1501 tb.tv_sec = DHCP_COARSE_TIMER_SECS;
1502 tb.tv_nsec = 0;
1503 net_dhcpcoarse_ticks = __lwp_wd_calc_ticks(&tb);
1504 __lwp_wd_initialize(&dhcp_coarsetimer_cntrl,__dhcpcoarse_timer,DHCPCOARSE_TIMER_ID,NULL);
1505 __lwp_wd_insert_ticks(&dhcp_coarsetimer_cntrl,net_dhcpcoarse_ticks);
1507 //setup fine timer
1508 tb.tv_sec = 0;
1509 tb.tv_nsec = DHCP_FINE_TIMER_MSECS*TB_NSPERMS;
1510 net_dhcpfine_ticks = __lwp_wd_calc_ticks(&tb);
1511 __lwp_wd_initialize(&dhcp_finetimer_cntrl,__dhcpfine_timer,DHCPFINE_TIMER_ID,NULL);
1512 __lwp_wd_insert_ticks(&dhcp_finetimer_cntrl,net_dhcpfine_ticks);
1514 //now start dhcp client
1515 dhcp_start(pnet);
1517 #endif
1518 } else
1519 return -1;
1521 // setup loopinterface
1522 IP4_ADDR(&loc_ip, 127,0,0,1);
1523 IP4_ADDR(&mask, 255,0,0,0);
1524 IP4_ADDR(&gw, 127,0,0,1);
1525 pnet = netif_add(&g_hLoopIF,&loc_ip,&mask,&gw,NULL,loopif_init,net_input);
1527 //last and least start the tcpip layer
1528 ret = net_init();
1530 if ( ret == 0 && use_dhcp == TRUE ) {
1532 int retries = 0;
1533 // wait for dhcp to bind
1534 while ( g_hNetIF.dhcp->state != DHCP_BOUND && retries < 20 ) {
1535 retries++;
1536 usleep(500000);
1539 if ( retries < 20 ) {
1540 //copy back network addresses
1541 if ( local_ip != NULL ) local_ip->s_addr = g_hNetIF.ip_addr.addr;
1542 if ( gateway != NULL ) gateway->s_addr = g_hNetIF.gw.addr;
1543 if ( netmask != NULL ) netmask->s_addr = g_hNetIF.netmask.addr;
1544 } else {
1545 ret = -2;
1549 return ret;
1552 s32 if_config(char *local_ip, char *netmask, char *gateway,boolean use_dhcp)
1554 s32 ret = 0;
1555 struct in_addr loc_ip, mask, gw;
1557 loc_ip.s_addr = 0;
1558 mask.s_addr = 0;
1559 gw.s_addr = 0;
1561 if ( local_ip != NULL ) loc_ip.s_addr = inet_addr(local_ip);
1562 if ( netmask != NULL ) mask.s_addr = inet_addr(netmask);
1563 if ( gateway != NULL ) gw.s_addr = inet_addr(gateway);
1565 ret = if_configex( &loc_ip, &mask, &gw, use_dhcp );
1567 if (ret<0) return ret;
1569 if ( use_dhcp == TRUE ) {
1570 //copy back network addresses
1571 if ( local_ip != NULL ) strcpy(local_ip, inet_ntoa( loc_ip ));
1572 if ( netmask != NULL ) strcpy(netmask, inet_ntoa( mask));
1573 if ( gateway != NULL ) strcpy(gateway, inet_ntoa( gw ));
1575 return ret;
1579 s32 net_init()
1581 sys_sem sem;
1583 if(tcpiplayer_inited) return 1;
1585 if(LWP_SemInit(&netsocket_sem,1,1)==-1) return -1;
1586 if(LWP_SemInit(&sockselect_sem,1,1)==-1) {
1587 LWP_SemDestroy(netsocket_sem);
1588 return -1;
1590 if(LWP_SemInit(&sem,0,1)==-1) {
1591 LWP_SemDestroy(netsocket_sem);
1592 LWP_SemDestroy(sockselect_sem);
1593 return -1;
1596 if(LWP_CreateThread(&hnet_thread,net_thread,(void*)sem,netthread_stack,STACKSIZE,220)==-1) {
1597 LWP_SemDestroy(netsocket_sem);
1598 LWP_SemDestroy(sockselect_sem);
1599 LWP_SemDestroy(sem);
1600 return -1;
1602 LWP_SemWait(sem);
1603 LWP_SemDestroy(sem);
1605 tcpiplayer_inited = 1;
1607 return 0;
1610 s32 net_shutdown(s32 s,u32 how)
1612 return -1;
1615 s32 net_fcntl(s32 s, u32 cmd, u32 flags)
1617 return -1;
1620 s32 net_socket(u32 domain,u32 type,u32 protocol)
1622 s32 i;
1623 struct netconn *conn;
1625 switch(type) {
1626 case SOCK_RAW:
1627 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_socket(SOCK_RAW)\n"));
1628 conn = netconn_new_with_proto_and_callback(NETCONN_RAW,protocol,evt_callback);
1629 break;
1630 case SOCK_DGRAM:
1631 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_socket(SOCK_DGRAM)\n"));
1632 conn = netconn_new_with_callback(NETCONN_UDP,evt_callback);
1633 break;
1634 case SOCK_STREAM:
1635 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_socket(SOCK_STREAM)\n"));
1636 conn = netconn_new_with_callback(NETCONN_TCP,evt_callback);
1637 break;
1638 default:
1639 return -1;
1641 if(!conn) return -1;
1643 i = alloc_socket(conn);
1644 if(i==-1) {
1645 netconn_delete(conn);
1646 return -1;
1649 conn->socket = i;
1650 return i;
1653 s32 net_accept(s32 s,struct sockaddr *addr,socklen_t *addrlen)
1655 struct netsocket *sock;
1656 struct netconn *newconn;
1657 struct ip_addr naddr = {0};
1658 u16 port = 0;
1659 s32 newsock;
1660 struct sockaddr_in sin;
1662 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_accept(%d)\n", s));
1664 sock = get_socket(s);
1665 if(!sock) return -1;
1667 newconn = netconn_accept(sock->conn);
1668 netconn_peer(newconn,&naddr,&port);
1670 memset(&sin,0,sizeof(sin));
1671 sin.sin_family = AF_INET;
1672 sin.sin_port = htons(port);
1673 sin.sin_addr.s_addr = naddr.addr;
1675 if(*addrlen>sizeof(sin))
1676 *addrlen = sizeof(sin);
1677 memcpy(addr,&sin,*addrlen);
1679 newsock = alloc_socket(newconn);
1680 if(newsock==-1) {
1681 netconn_delete(newconn);
1682 return -1;
1685 newconn->callback = evt_callback;
1686 sock = get_socket(newsock);
1688 LWP_SemWait(netsocket_sem);
1689 sock->rcvevt += -1 - newconn->socket;
1690 newconn->socket = newsock;
1691 LWP_SemPost(netsocket_sem);
1693 return newsock;
1696 s32 net_bind(s32 s,struct sockaddr *name,socklen_t namelen)
1698 struct netsocket *sock;
1699 struct ip_addr loc_addr;
1700 u16 loc_port;
1701 err_t err;
1703 sock = get_socket(s);
1704 if(!sock) return -1;
1706 loc_addr.addr = ((struct sockaddr_in*)name)->sin_addr.s_addr;
1707 loc_port = ((struct sockaddr_in*)name)->sin_port;
1709 err = netconn_bind(sock->conn,&loc_addr,ntohs(loc_port));
1710 if(err!=ERR_OK) return -1;
1712 return 0;
1715 s32 net_listen(s32 s,u32 backlog)
1717 struct netsocket *sock;
1718 err_t err;
1720 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_listen(%d, backlog=%d)\n", s, backlog));
1721 sock = get_socket(s);
1722 if(!sock) return -1;
1724 err = netconn_listen(sock->conn);
1725 if(err!=ERR_OK) {
1726 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_listen(%d) failed, err=%d\n", s, err));
1727 return -1;
1729 return 0;
1732 s32 net_recvfrom(s32 s,void *mem,s32 len,u32 flags,struct sockaddr *from,socklen_t *fromlen)
1734 struct netsocket *sock;
1735 struct netbuf *buf;
1736 u16 buflen,copylen;
1737 struct ip_addr *addr;
1738 u16 port;
1740 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
1741 if(mem==NULL || len<=0) return -1;
1743 sock = get_socket(s);
1744 if(!sock) return -1;
1746 if(sock->lastdata)
1747 buf = sock->lastdata;
1748 else {
1749 if(((flags&MSG_DONTWAIT) || (sock->flags&O_NONBLOCK)) && !sock->rcvevt) {
1750 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_recvfrom(%d): returning EWOULDBLOCK\n", s));
1751 return -1;
1753 buf = netconn_recv(sock->conn);
1754 if(!buf) {
1755 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_recvfrom(%d): buf == NULL!\n", s));
1756 return 0;
1760 buflen = netbuf_len(buf);
1761 buflen -= sock->lastoffset;
1762 if(buflen<=0)
1763 return 0;
1764 if(len>buflen)
1765 copylen = buflen;
1766 else
1767 copylen = len;
1769 netbuf_copypartial(buf,mem,copylen,sock->lastoffset);
1771 if(from && fromlen) {
1772 struct sockaddr_in sin;
1774 addr = netbuf_fromaddr(buf);
1775 port = netbuf_fromport(buf);
1777 memset(&sin,0,sizeof(sin));
1778 sin.sin_family = AF_INET;
1779 sin.sin_port = htons(port);
1780 sin.sin_addr.s_addr = addr->addr;
1782 if(*fromlen>sizeof(sin))
1783 *fromlen = sizeof(sin);
1785 memcpy(from,&sin,*fromlen);
1787 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_recvfrom(%d): addr=", s));
1788 ip_addr_debug_print(SOCKETS_DEBUG, addr);
1789 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
1791 if(netconn_type(sock->conn)==NETCONN_TCP && (buflen-copylen)>0) {
1792 sock->lastdata = buf;
1793 sock->lastoffset += copylen;
1794 } else {
1795 sock->lastdata = NULL;
1796 sock->lastoffset = 0;
1797 netbuf_delete(buf);
1799 return copylen;
1802 s32 net_read(s32 s,void *mem,s32 len)
1804 return net_recvfrom(s,mem,len,0,NULL,NULL);
1807 s32 net_recv(s32 s,void *mem,s32 len,u32 flags)
1809 return net_recvfrom(s,mem,len,flags,NULL,NULL);
1812 s32 net_sendto(s32 s,const void *data,s32 len,u32 flags,struct sockaddr *to,socklen_t tolen)
1814 struct netsocket *sock;
1815 struct ip_addr remote_addr, addr;
1816 u16_t remote_port, port = 0;
1817 s32 ret,connected;
1819 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_sendto(%d, data=%p, size=%d, flags=0x%x)\n", s, data, len, flags));
1820 if(data==NULL || len<=0) return -1;
1822 sock = get_socket(s);
1823 if (!sock) return -1;
1825 /* get the peer if currently connected */
1826 connected = (netconn_peer(sock->conn, &addr, &port) == ERR_OK);
1828 remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
1829 remote_port = ((struct sockaddr_in *)to)->sin_port;
1831 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, len, flags));
1832 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
1833 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port)));
1835 netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
1837 ret = net_send(s, data, len, flags);
1839 /* reset the remote address and port number
1840 of the connection */
1841 if (connected)
1842 netconn_connect(sock->conn, &addr, port);
1843 else
1844 netconn_disconnect(sock->conn);
1845 return ret;
1848 s32 net_send(s32 s,const void *data,s32 len,u32 flags)
1850 struct netsocket *sock;
1851 struct netbuf *buf;
1852 err_t err;
1854 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, len, flags));
1855 if(data==NULL || len<=0) return -1;
1857 sock = get_socket(s);
1858 if(!sock) return -1;
1860 switch(netconn_type(sock->conn)) {
1861 case NETCONN_RAW:
1862 case NETCONN_UDP:
1863 case NETCONN_UDPLITE:
1864 case NETCONN_UDPNOCHKSUM:
1865 buf = netbuf_new();
1866 if(!buf) {
1867 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_send(%d) ENOBUFS\n", s));
1868 return -1;
1870 netbuf_ref(buf,data,len);
1871 err = netconn_send(sock->conn,buf);
1872 netbuf_delete(buf);
1873 break;
1874 case NETCONN_TCP:
1875 err = netconn_write(sock->conn,data,len,NETCONN_COPY);
1876 break;
1877 default:
1878 err = ERR_ARG;
1879 break;
1881 if(err!=ERR_OK) {
1882 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_send(%d) err=%d\n", s, err));
1883 return -1;
1886 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_send(%d) ok size=%d\n", s, len));
1887 return len;
1890 s32 net_write(s32 s,const void *data,s32 size)
1892 return net_send(s,data,size,0);
1895 s32 net_connect(s32 s,struct sockaddr *name,socklen_t namelen)
1897 struct netsocket *sock;
1898 err_t err;
1900 sock = get_socket(s);
1901 if(!sock) return -1;
1903 if(((struct sockaddr_in*)name)->sin_family==AF_UNSPEC) {
1904 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_connect(%d, AF_UNSPEC)\n", s));
1905 err = netconn_disconnect(sock->conn);
1906 } else {
1907 struct ip_addr remote_addr;
1908 u16 remote_port;
1910 remote_addr.addr = ((struct sockaddr_in*)name)->sin_addr.s_addr;
1911 remote_port = ((struct sockaddr_in*)name)->sin_port;
1913 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_connect(%d, addr=", s));
1914 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
1915 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));
1917 err = netconn_connect(sock->conn,&remote_addr,ntohs(remote_port));
1919 if(err!=ERR_OK) {
1920 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_connect(%d) failed, err=%d\n", s, err));
1921 return -1;
1924 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_connect(%d) succeeded\n", s));
1925 return 0;
1928 s32 net_close(s32 s)
1930 struct netsocket *sock;
1932 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_close(%d)\n", s));
1934 LWP_SemWait(netsocket_sem);
1936 sock = get_socket(s);
1937 if(!sock) {
1938 LWP_SemPost(netsocket_sem);
1939 return -1;
1942 netconn_delete(sock->conn);
1943 if(sock->lastdata) netbuf_delete(sock->lastdata);
1945 sock->lastdata = NULL;
1946 sock->lastoffset = 0;
1947 sock->conn = NULL;
1949 LWP_SemPost(netsocket_sem);
1950 return 0;
1953 static s32 net_selscan(s32 maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset)
1955 s32 i,nready = 0;
1956 fd_set lreadset,lwriteset,lexceptset;
1957 struct netsocket *sock;
1959 FD_ZERO(&lreadset);
1960 FD_ZERO(&lwriteset);
1961 FD_ZERO(&lexceptset);
1963 for(i=0;i<maxfdp1;i++) {
1964 if(FD_ISSET(i,readset)) {
1965 sock = get_socket(i);
1966 if(sock && (sock->lastdata || sock->rcvevt)) {
1967 FD_SET(i,&lreadset);
1968 nready++;
1971 if(FD_ISSET(i,writeset)) {
1972 sock = get_socket(i);
1973 if(sock && sock->sendevt) {
1974 FD_SET(i,&lwriteset);
1975 nready++;
1979 *readset = lreadset;
1980 *writeset = lwriteset;
1981 FD_ZERO(exceptset);
1983 return nready;
1986 s32 net_select(s32 maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,struct timeval *timeout)
1988 s32 i,nready;
1989 fd_set lreadset,lwriteset,lexceptset;
1990 struct timespec tb,*p_tb;
1991 struct netselect_cb sel_cb;
1992 struct netselect_cb *psel_cb;
1994 sel_cb.next = NULL;
1995 sel_cb.readset = readset;
1996 sel_cb.writeset = writeset;
1997 sel_cb.exceptset = exceptset;
1998 sel_cb.signaled = 0;
2000 LWP_SemWait(sockselect_sem);
2002 if(readset)
2003 lreadset = *readset;
2004 else
2005 FD_ZERO(&lreadset);
2007 if(writeset)
2008 lwriteset = *writeset;
2009 else
2010 FD_ZERO(&lwriteset);
2012 if(exceptset)
2013 lexceptset = *exceptset;
2014 else
2015 FD_ZERO(&lexceptset);
2017 nready = net_selscan(maxfdp1,&lreadset,&lwriteset,&lexceptset);
2018 if(!nready) {
2019 if(timeout && timeout->tv_sec==0 && timeout->tv_usec==0) {
2020 LWP_SemPost(sockselect_sem);
2021 if(readset)
2022 FD_ZERO(readset);
2023 if(writeset)
2024 FD_ZERO(writeset);
2025 if(exceptset)
2026 FD_ZERO(exceptset);
2027 return 0;
2030 LWP_MutexInit(&sel_cb.cond_lck,FALSE);
2031 LWP_CondInit(&sel_cb.cond);
2032 sel_cb.next = selectcb_list;
2033 selectcb_list = &sel_cb;
2035 LWP_SemPost(sockselect_sem);
2036 if(timeout==NULL)
2037 p_tb = NULL;
2038 else {
2039 tb.tv_sec = timeout->tv_sec;
2040 tb.tv_nsec = (timeout->tv_usec+500)*TB_NSPERUS;
2041 p_tb = &tb;
2044 LWP_MutexLock(sel_cb.cond_lck);
2045 i = LWP_CondTimedWait(sel_cb.cond,sel_cb.cond_lck,p_tb);
2046 LWP_MutexUnlock(sel_cb.cond_lck);
2048 LWP_SemWait(sockselect_sem);
2049 if(selectcb_list==&sel_cb)
2050 selectcb_list = sel_cb.next;
2051 else {
2052 for(psel_cb = selectcb_list;psel_cb;psel_cb = psel_cb->next) {
2053 if(psel_cb->next==&sel_cb) {
2054 psel_cb->next = sel_cb.next;
2055 break;
2059 LWP_CondDestroy(sel_cb.cond);
2060 LWP_MutexDestroy(sel_cb.cond_lck);
2062 LWP_SemPost(sockselect_sem);
2064 if(i==ETIMEDOUT) {
2065 if(readset)
2066 FD_ZERO(readset);
2067 if(writeset)
2068 FD_ZERO(writeset);
2069 if(exceptset)
2070 FD_ZERO(exceptset);
2071 return 0;
2074 if(readset)
2075 lreadset = *readset;
2076 else
2077 FD_ZERO(&lreadset);
2079 if(writeset)
2080 lwriteset = *writeset;
2081 else
2082 FD_ZERO(&lwriteset);
2084 if(exceptset)
2085 lexceptset = *exceptset;
2086 else
2087 FD_ZERO(&lexceptset);
2089 nready = net_selscan(maxfdp1,&lreadset,&lwriteset,&lexceptset);
2090 } else
2091 LWP_SemPost(sockselect_sem);
2093 if(readset)
2094 *readset = lreadset;
2095 if(writeset)
2096 *writeset = lwriteset;
2097 if(exceptset)
2098 *exceptset = lexceptset;
2100 return nready;
2103 s32 net_setsockopt(s32 s,u32 level,u32 optname,const void *optval,socklen_t optlen)
2105 s32 err = 0;
2106 struct netsocket *sock;
2108 sock = get_socket(s);
2109 if(sock==NULL) return -1;
2110 if(optval==NULL) return -1;
2112 switch(level) {
2113 case SOL_SOCKET:
2115 switch(optname) {
2116 case SO_BROADCAST:
2117 case SO_KEEPALIVE:
2118 case SO_REUSEADDR:
2119 case SO_REUSEPORT:
2120 if(optlen<sizeof(u32)) err = EINVAL;
2121 break;
2122 default:
2123 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
2124 err = ENOPROTOOPT;
2127 break;
2129 case IPPROTO_IP:
2131 switch(optname) {
2132 case IP_TTL:
2133 case IP_TOS:
2134 if(optlen<sizeof(u32)) err = EINVAL;
2135 break;
2136 default:
2137 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
2138 err = ENOPROTOOPT;
2141 break;
2143 case IPPROTO_TCP:
2145 if(optlen<sizeof(u32)) {
2146 err = EINVAL;
2147 break;
2149 if(sock->conn->type!=NETCONN_TCP) return 0;
2151 switch(optname) {
2152 case TCP_NODELAY:
2153 case TCP_KEEPALIVE:
2154 break;
2155 default:
2156 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
2157 err = ENOPROTOOPT;
2160 break;
2162 default:
2163 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
2164 err = ENOPROTOOPT;
2166 if(err!=0) return -1;
2168 switch(level) {
2169 case SOL_SOCKET:
2171 switch(optname) {
2172 case SO_BROADCAST:
2173 case SO_KEEPALIVE:
2174 case SO_REUSEADDR:
2175 case SO_REUSEPORT:
2176 if(*(u32*)optval)
2177 sock->conn->pcb.tcp->so_options |= optname;
2178 else
2179 sock->conn->pcb.tcp->so_options &= ~optname;
2180 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(u32*)optval?"on":"off")));
2181 break;
2184 break;
2186 case IPPROTO_IP:
2188 switch(optname) {
2189 case IP_TTL:
2190 sock->conn->pcb.tcp->ttl = (u8)(*(u32*)optval);
2191 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %u\n", s, sock->conn->pcb.tcp->ttl));
2192 break;
2193 case IP_TOS:
2194 sock->conn->pcb.tcp->tos = (u8)(*(u32*)optval);
2195 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n", s, sock->conn->pcb.tcp->tos));
2196 break;
2199 break;
2201 case IPPROTO_TCP:
2203 switch(optname) {
2204 case TCP_NODELAY:
2205 if(*(u32*)optval)
2206 sock->conn->pcb.tcp->flags |= TF_NODELAY;
2207 else
2208 sock->conn->pcb.tcp->flags &= ~TF_NODELAY;
2209 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", s, (*(u32*)optval)?"on":"off") );
2210 break;
2211 case TCP_KEEPALIVE:
2212 sock->conn->pcb.tcp->keepalive = (u32)(*(u32*)optval);
2213 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %u\n", s, sock->conn->pcb.tcp->keepalive));
2214 break;
2218 return err?-1:0;
2221 s32 net_ioctl(s32 s, u32 cmd, void *argp)
2223 struct netsocket *sock = get_socket(s);
2225 if(!sock) return -1;
2227 switch (cmd) {
2228 case FIONREAD:
2229 if(!argp) return -1;
2231 *((u16_t*)argp) = sock->conn->recvavail;
2233 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16*)argp)));
2234 return 0;
2236 case FIONBIO:
2237 if(argp && *(u32*)argp)
2238 sock->flags |= O_NONBLOCK;
2239 else
2240 sock->flags &= ~O_NONBLOCK;
2241 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags&O_NONBLOCK)));
2242 return 0;
2244 default:
2245 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
2246 return -1;