SMB: non-blocking sockets
[libogc.git] / lwip / network.c
blob450f4e563e71bafb54ca210b2f5a43dba2629535
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_alloc(struct netbuf *,u32);
93 static void netbuf_free(struct netbuf *);
94 static void netbuf_copypartial(struct netbuf *,void *,u32,u32);
95 static void netbuf_ref(struct netbuf *,const void *,u32);
97 static struct netconn* netconn_new_with_callback(enum netconn_type,void (*)(struct netconn *,enum netconn_evt,u32));
98 static struct netconn* netconn_new_with_proto_and_callback(enum netconn_type,u16,void (*)(struct netconn *,enum netconn_evt,u32));
99 static err_t netconn_delete(struct netconn *);
100 static struct netconn* netconn_accept(struct netconn* );
101 static err_t netconn_peer(struct netconn *,struct ip_addr *,u16 *);
102 static err_t netconn_bind(struct netconn *,struct ip_addr *,u16);
103 static err_t netconn_listen(struct netconn *);
104 static struct netbuf* netconn_recv(struct netconn *);
105 static err_t netconn_send(struct netconn *,struct netbuf *);
106 static err_t netconn_write(struct netconn *,const void *,u32,u8);
107 static err_t netconn_connect(struct netconn *,struct ip_addr *,u16);
108 static err_t netconn_disconnect(struct netconn *);
110 static void do_newconn(struct apimsg_msg *);
111 static void do_delconn(struct apimsg_msg *);
112 static void do_bind(struct apimsg_msg *);
113 static void do_listen(struct apimsg_msg *);
114 static void do_connect(struct apimsg_msg *);
115 static void do_disconnect(struct apimsg_msg *);
116 static void do_accept(struct apimsg_msg *);
117 static void do_send(struct apimsg_msg *);
118 static void do_recv(struct apimsg_msg *);
119 static void do_write(struct apimsg_msg *);
120 static void do_close(struct apimsg_msg *);
122 static apimsg_decode decode[APIMSG_MAX] = {
123 do_newconn,
124 do_delconn,
125 do_bind,
126 do_connect,
127 do_disconnect,
128 do_listen,
129 do_accept,
130 do_send,
131 do_recv,
132 do_write,
133 do_close
136 static void apimsg_post(struct api_msg *);
138 static err_t net_input(struct pbuf *,struct netif *);
139 static void net_apimsg(struct api_msg *);
140 static err_t net_callback(void (*)(void *),void *);
141 static void* net_thread(void *);
143 static void tmr_callback(void *arg)
145 void (*functor)() = (void(*)())arg;
146 if(functor) functor();
149 /* low level stuff */
150 static void __dhcpcoarse_timer(void *arg)
152 __lwp_thread_dispatchdisable();
153 net_callback(tmr_callback,(void*)dhcp_coarse_tmr);
154 __lwp_wd_insert_ticks(&dhcp_coarsetimer_cntrl,net_dhcpcoarse_ticks);
155 __lwp_thread_dispatchunnest();
158 static void __dhcpfine_timer(void *arg)
160 __lwp_thread_dispatchdisable();
161 net_callback(tmr_callback,(void*)dhcp_fine_tmr);
162 __lwp_wd_insert_ticks(&dhcp_finetimer_cntrl,net_dhcpfine_ticks);
163 __lwp_thread_dispatchunnest();
166 static void __tcp_timer(void *arg)
168 #ifdef _NET_DEBUG
169 printf("__tcp_timer(%d,%p,%p)\n",tcp_timer_active,tcp_active_pcbs,tcp_tw_pcbs);
170 #endif
171 __lwp_thread_dispatchdisable();
172 net_callback(tmr_callback,(void*)tcp_tmr);
173 if (tcp_active_pcbs || tcp_tw_pcbs) {
174 __lwp_wd_insert_ticks(&tcp_timer_cntrl,net_tcp_ticks);
175 } else
176 tcp_timer_active = 0;
177 __lwp_thread_dispatchunnest();
180 static void __arp_timer(void *arg)
182 __lwp_thread_dispatchdisable();
183 net_callback(tmr_callback,(void*)etharp_tmr);
184 __lwp_wd_insert_ticks(&arp_time_cntrl,net_arp_ticks);
185 __lwp_thread_dispatchunnest();
188 void tcp_timer_needed(void)
190 #ifdef _NET_DEBUG
191 printf("tcp_timer_needed()\n");
192 #endif
193 if(!tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
194 tcp_timer_active = 1;
195 __lwp_wd_insert_ticks(&tcp_timer_cntrl,net_tcp_ticks);
199 /* netbuf part */
200 static __inline__ u16 netbuf_len(struct netbuf *buf)
202 return ((buf && buf->p)?buf->p->tot_len:0);
205 static __inline__ struct ip_addr* netbuf_fromaddr(struct netbuf *buf)
207 return (buf?buf->fromaddr:NULL);
210 static __inline__ u16 netbuf_fromport(struct netbuf *buf)
212 return (buf?buf->fromport:0);
215 static void netbuf_copypartial(struct netbuf *buf,void *dataptr,u32 len,u32 offset)
217 struct pbuf *p;
218 u16 i,left;
220 left = 0;
221 if(buf==NULL || dataptr==NULL) return;
223 for(p=buf->p;left<len && p!=NULL;p=p->next) {
224 if(offset!=0 && offset>=p->len)
225 offset -= p->len;
226 else {
227 for(i=offset;i<p->len;i++) {
228 ((u8*)dataptr)[left] = ((u8*)p->payload)[i];
229 if(++left>=len) return;
231 offset = 0;
236 static struct netbuf* netbuf_new()
238 struct netbuf *buf = NULL;
240 buf = memp_malloc(MEMP_NETBUF);
241 if(buf) {
242 buf->p = NULL;
243 buf->ptr = NULL;
245 return buf;
248 static void netbuf_delete(struct netbuf *buf)
250 if(buf!=NULL) {
251 if(buf->p!=NULL) pbuf_free(buf->p);
252 memp_free(MEMP_NETBUF,buf);
256 static void* netbuf_alloc(struct netbuf *buf,u32 size)
258 if(buf->p!=NULL) pbuf_free(buf->p);
260 buf->p = pbuf_alloc(PBUF_TRANSPORT,size,PBUF_RAM);
261 if(buf->p==NULL) return NULL;
263 buf->ptr = buf->p;
264 return buf->p->payload;
267 static void netbuf_free(struct netbuf *buf)
269 if(buf->p!=NULL) pbuf_free(buf->p);
270 buf->p = buf->ptr = NULL;
273 static void netbuf_ref(struct netbuf *buf, const void *dataptr,u32 size)
275 if(buf->p!=NULL) pbuf_free(buf->p);
276 buf->p = pbuf_alloc(PBUF_TRANSPORT,0,PBUF_REF);
277 buf->p->payload = (void*)dataptr;
278 buf->p->len = buf->p->tot_len = size;
279 buf->ptr = buf->p;
282 /* netconn part */
283 static inline enum netconn_type netconn_type(struct netconn *conn)
285 return conn->type;
288 static struct netconn* netconn_new_with_callback(enum netconn_type t,void (*cb)(struct netconn*,enum netconn_evt,u32))
290 return netconn_new_with_proto_and_callback(t,0,cb);
293 static struct netconn* netconn_new_with_proto_and_callback(enum netconn_type t,u16 proto,void (*cb)(struct netconn *,enum netconn_evt,u32))
295 u32 dummy = 0;
296 struct netconn *conn;
297 struct api_msg *msg;
299 conn = memp_malloc(MEMP_NETCONN);
300 if(!conn) return NULL;
302 conn->err = ERR_OK;
303 conn->type = t;
304 conn->pcb.tcp = NULL;
306 if(MQ_Init(&conn->mbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) {
307 memp_free(MEMP_NETCONN,conn);
308 return NULL;
310 if(LWP_SemInit(&conn->sem,0,1)==-1) {
311 MQ_Close(conn->mbox);
312 memp_free(MEMP_NETCONN,conn);
313 return NULL;
316 conn->acceptmbox = SYS_MBOX_NULL;
317 conn->recvmbox = SYS_MBOX_NULL;
318 conn->state = NETCONN_NONE;
319 conn->socket = 0;
320 conn->callback = cb;
321 conn->recvavail = 0;
323 msg = memp_malloc(MEMP_API_MSG);
324 if(!msg) {
325 MQ_Close(conn->mbox);
326 memp_free(MEMP_NETCONN,conn);
327 return NULL;
330 msg->type = APIMSG_NEWCONN;
331 msg->msg.msg.bc.port = proto;
332 msg->msg.conn = conn;
333 apimsg_post(msg);
334 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
335 memp_free(MEMP_API_MSG,msg);
337 if(conn->err!=ERR_OK) {
338 MQ_Close(conn->mbox);
339 memp_free(MEMP_NETCONN,conn);
340 return NULL;
342 return conn;
345 static err_t netconn_delete(struct netconn *conn)
347 u32 dummy = 0;
348 struct api_msg *msg;
349 sys_mbox mbox;
350 void *mem;
352 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_delete(%p)\n", conn));
354 if(!conn) return ERR_OK;
356 msg = memp_malloc(MEMP_API_MSG);
357 if(!msg) return ERR_MEM;
359 msg->type = APIMSG_DELCONN;
360 msg->msg.conn = conn;
361 apimsg_post(msg);
362 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
363 memp_free(MEMP_API_MSG,msg);
365 mbox = conn->recvmbox;
366 conn->recvmbox = SYS_MBOX_NULL;
367 if(mbox!=SYS_MBOX_NULL) {
368 while(MQ_Receive(mbox,(mqmsg_t)&mem,MQ_MSG_NOBLOCK)==TRUE) {
369 if(mem!=NULL) {
370 if(conn->type==NETCONN_TCP)
371 pbuf_free((struct pbuf*)mem);
372 else
373 netbuf_delete((struct netbuf*)mem);
376 MQ_Close(mbox);
379 mbox = conn->acceptmbox;
380 conn->acceptmbox = SYS_MBOX_NULL;
381 if(mbox!=SYS_MBOX_NULL) {
382 while(MQ_Receive(mbox,(mqmsg_t)&mem,MQ_MSG_NOBLOCK)==TRUE) {
383 if(mem!=NULL) netconn_delete((struct netconn*)mem);
385 MQ_Close(mbox);
388 MQ_Close(conn->mbox);
389 conn->mbox = SYS_MBOX_NULL;
391 LWP_SemDestroy(conn->sem);
392 conn->sem = SYS_SEM_NULL;
394 memp_free(MEMP_NETCONN,conn);
395 return ERR_OK;
398 static struct netconn* netconn_accept(struct netconn* conn)
400 struct netconn *newconn;
402 if(conn==NULL) return NULL;
404 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_accept(%p)\n", conn));
405 MQ_Receive(conn->acceptmbox,(mqmsg_t)&newconn,MQ_MSG_BLOCK);
406 if(conn->callback)
407 (*conn->callback)(conn,NETCONN_EVTRCVMINUS,0);
409 return newconn;
412 static err_t netconn_peer(struct netconn *conn,struct ip_addr *addr,u16 *port)
414 switch(conn->type) {
415 case NETCONN_RAW:
416 return ERR_CONN;
417 case NETCONN_UDPLITE:
418 case NETCONN_UDPNOCHKSUM:
419 case NETCONN_UDP:
420 if(conn->pcb.udp==NULL || ((conn->pcb.udp->flags&UDP_FLAGS_CONNECTED)==0))
421 return ERR_CONN;
422 *addr = conn->pcb.udp->remote_ip;
423 *port = conn->pcb.udp->remote_port;
424 break;
425 case NETCONN_TCP:
426 if(conn->pcb.tcp==NULL)
427 return ERR_CONN;
428 *addr = conn->pcb.tcp->remote_ip;
429 *port = conn->pcb.tcp->remote_port;
430 break;
432 return (conn->err = ERR_OK);
435 static err_t netconn_bind(struct netconn *conn,struct ip_addr *addr,u16 port)
437 u32 dummy = 0;
438 struct api_msg *msg;
440 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_bind(%p)\n", conn));
442 if(conn==NULL) return ERR_VAL;
443 if(conn->type!=NETCONN_TCP && conn->recvmbox==SYS_MBOX_NULL) {
444 if(MQ_Init(&conn->recvmbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) return ERR_MEM;
447 if((msg=memp_malloc(MEMP_API_MSG))==NULL)
448 return (conn->err = ERR_MEM);
450 msg->type = APIMSG_BIND;
451 msg->msg.conn = conn;
452 msg->msg.msg.bc.ipaddr = addr;
453 msg->msg.msg.bc.port = port;
454 apimsg_post(msg);
455 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
456 memp_free(MEMP_API_MSG,msg);
457 return conn->err;
460 static err_t netconn_listen(struct netconn *conn)
462 u32 dummy = 0;
463 struct api_msg *msg;
465 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_listen(%p)\n", conn));
467 if(conn==NULL) return -1;
468 if(conn->acceptmbox==SYS_MBOX_NULL) {
469 if(MQ_Init(&conn->acceptmbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) return ERR_MEM;
472 if((msg=memp_malloc(MEMP_API_MSG))==NULL) return (conn->err = ERR_MEM);
473 msg->type = APIMSG_LISTEN;
474 msg->msg.conn = conn;
475 apimsg_post(msg);
476 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
477 memp_free(MEMP_API_MSG,msg);
478 return conn->err;
481 static struct netbuf* netconn_recv(struct netconn *conn)
483 u32 dummy = 0;
484 struct api_msg *msg;
485 struct netbuf *buf;
486 struct pbuf *p;
487 u16 len;
489 if(conn==NULL) return NULL;
490 if(conn->recvmbox==SYS_MBOX_NULL) {
491 conn->err = ERR_CONN;
492 return NULL;
494 if(conn->err!=ERR_OK) return NULL;
496 if(conn->type==NETCONN_TCP) {
497 if(conn->pcb.tcp->state==LISTEN) {
498 conn->err = ERR_CONN;
499 return NULL;
502 buf = memp_malloc(MEMP_NETBUF);
503 if(buf==NULL) {
504 conn->err = ERR_MEM;
505 return NULL;
508 MQ_Receive(conn->recvmbox,(mqmsg_t)&p,MQ_MSG_BLOCK);
509 if(p!=NULL) {
510 len = p->tot_len;
511 conn->recvavail -= len;
512 } else
513 len = 0;
515 if(conn->callback)
516 (*conn->callback)(conn,NETCONN_EVTRCVMINUS,len);
518 if(p==NULL) {
519 memp_free(MEMP_NETBUF,buf);
520 MQ_Close(conn->recvmbox);
521 conn->recvmbox = SYS_MBOX_NULL;
522 return NULL;
525 buf->p = p;
526 buf->ptr = p;
527 buf->fromport = 0;
528 buf->fromaddr = NULL;
530 if((msg=memp_malloc(MEMP_API_MSG))==NULL) {
531 conn->err = ERR_MEM;
532 return buf;
535 msg->type = APIMSG_RECV;
536 msg->msg.conn = conn;
537 if(buf!=NULL)
538 msg->msg.msg.len = len;
539 else
540 msg->msg.msg.len = 1;
542 apimsg_post(msg);
543 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
544 memp_free(MEMP_API_MSG,msg);
545 } else {
546 MQ_Receive(conn->recvmbox,(mqmsg_t)&buf,MQ_MSG_BLOCK);
547 conn->recvavail -= buf->p->tot_len;
548 if(conn->callback)
549 (*conn->callback)(conn,NETCONN_EVTRCVMINUS,buf->p->tot_len);
552 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void *)buf, conn->err));
553 return buf;
556 static err_t netconn_send(struct netconn *conn,struct netbuf *buf)
558 u32 dummy = 0;
559 struct api_msg *msg;
561 if(conn==NULL) return ERR_VAL;
562 if(conn->err!=ERR_OK) return conn->err;
563 if((msg=memp_malloc(MEMP_API_MSG))==NULL) return (conn->err = ERR_MEM);
565 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
566 msg->type = APIMSG_SEND;
567 msg->msg.conn = conn;
568 msg->msg.msg.p = buf->p;
569 apimsg_post(msg);
570 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
571 memp_free(MEMP_API_MSG,msg);
572 return conn->err;
575 static err_t netconn_write(struct netconn *conn,const void *dataptr,u32 size,u8 copy)
577 u32 dummy = 0;
578 struct api_msg *msg;
579 u16 len,snd_buf;
582 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write(%d)\n",conn->err));
584 if(conn==NULL) return ERR_VAL;
585 if(conn->err!=ERR_OK) return conn->err;
587 if((msg=memp_malloc(MEMP_API_MSG))==NULL) return (conn->err = ERR_MEM);
589 msg->type = APIMSG_WRITE;
590 msg->msg.conn = conn;
591 conn->state = NETCONN_WRITE;
592 while(conn->err==ERR_OK && size>0) {
593 msg->msg.msg.w.dataptr = (void*)dataptr;
594 msg->msg.msg.w.copy = copy;
595 if(conn->type==NETCONN_TCP) {
596 while((snd_buf=tcp_sndbuf(conn->pcb.tcp))==0) {
597 LWIP_DEBUGF(API_LIB_DEBUG,("netconn_write: tcp_sndbuf = 0,err = %d\n", conn->err));
598 LWP_SemWait(conn->sem);
599 if(conn->err!=ERR_OK) goto ret;
601 if(size>snd_buf)
602 len = snd_buf;
603 else
604 len = size;
605 } else
606 len = size;
608 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
609 msg->msg.msg.w.len = len;
610 apimsg_post(msg);
611 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
612 if(conn->err==ERR_OK) {
613 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: %d bytes written\n",len));
614 dataptr = (void*)((char*)dataptr+len);
615 size -= len;
616 } else if(conn->err==ERR_MEM) {
617 LWIP_DEBUGF(API_LIB_DEBUG,("netconn_write: mem err\n"));
618 conn->err = ERR_OK;
619 LWP_SemWait(conn->sem);
620 } else {
621 LWIP_DEBUGF(API_LIB_DEBUG,("netconn_write: err = %d\n", conn->err));
622 break;
625 ret:
626 memp_free(MEMP_API_MSG,msg);
627 conn->state = NETCONN_NONE;
629 return conn->err;
632 static err_t netconn_connect(struct netconn *conn,struct ip_addr *addr,u16 port)
634 u32 dummy = 0;
635 struct api_msg *msg;
637 if(conn==NULL) return -1;
638 if(conn->recvmbox==SYS_MBOX_NULL) {
639 if(MQ_Init(&conn->recvmbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) return ERR_MEM;
642 if((msg=memp_malloc(MEMP_API_MSG))==NULL) return ERR_MEM;
644 msg->type = APIMSG_CONNECT;
645 msg->msg.conn = conn;
646 msg->msg.msg.bc.ipaddr = addr;
647 msg->msg.msg.bc.port = port;
648 apimsg_post(msg);
649 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
650 memp_free(MEMP_API_MSG,msg);
651 return conn->err;
654 static err_t netconn_disconnect(struct netconn *conn)
656 u32 dummy = 0;
657 struct api_msg *msg;
659 if(conn==NULL) return ERR_VAL;
660 if((msg=memp_malloc(MEMP_API_MSG))==NULL) return ERR_MEM;
662 msg->type = APIMSG_DISCONNECT;
663 msg->msg.conn = conn;
664 apimsg_post(msg);
665 MQ_Receive(conn->mbox,(mqmsg_t)&dummy,MQ_MSG_BLOCK);
666 memp_free(MEMP_API_MSG,msg);
667 return conn->err;
670 /* api msg part */
671 static u8_t recv_raw(void *arg,struct raw_pcb *pcb,struct pbuf *p,struct ip_addr *addr)
673 struct netbuf *buf;
674 struct netconn *conn = (struct netconn*)arg;
676 if(!conn) return 0;
678 if(conn->recvmbox!=SYS_MBOX_NULL) {
679 if((buf=memp_malloc(MEMP_NETBUF))==NULL) return 0;
681 pbuf_ref(p);
682 buf->p = p;
683 buf->ptr = p;
684 buf->fromaddr = addr;
685 buf->fromport = pcb->protocol;
687 conn->recvavail += p->tot_len;
688 if(conn->callback)
689 (*conn->callback)(conn,NETCONN_EVTRCVPLUS,p->tot_len);
690 MQ_Send(conn->recvmbox,&buf,MQ_MSG_BLOCK);
692 return 0;
695 static void recv_udp(void *arg,struct udp_pcb *pcb,struct pbuf *p,struct ip_addr *addr,u16 port)
697 struct netbuf *buf;
698 struct netconn *conn = (struct netconn*)arg;
700 if(!conn) {
701 pbuf_free(p);
702 return;
705 if(conn->recvmbox!=SYS_MBOX_NULL) {
706 buf = memp_malloc(MEMP_NETBUF);
707 if(!buf) {
708 pbuf_free(p);
709 return;
711 buf->p = p;
712 buf->ptr = p;
713 buf->fromaddr = addr;
714 buf->fromport = port;
716 conn->recvavail += p->tot_len;
717 if(conn->callback)
718 (*conn->callback)(conn,NETCONN_EVTRCVPLUS,p->tot_len);
720 MQ_Send(conn->recvmbox,&buf,MQ_MSG_BLOCK);
724 static err_t recv_tcp(void *arg,struct tcp_pcb *pcb,struct pbuf *p,err_t err)
726 u16 len;
727 struct netconn *conn = (struct netconn*)arg;
729 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: recv_tcp(%p,%p,%p,%d)\n",arg,pcb,p,err));
731 if(conn==NULL) {
732 pbuf_free(p);
733 return ERR_VAL;
736 if(conn->recvmbox!=SYS_MBOX_NULL) {
737 conn->err = err;
738 if(p!=NULL) {
739 len = p->tot_len;
740 conn->recvavail += len;
741 } else len = 0;
743 if(conn->callback)
744 (*conn->callback)(conn,NETCONN_EVTRCVPLUS,len);
746 MQ_Send(conn->recvmbox,&p,MQ_MSG_BLOCK);
748 return ERR_OK;
751 static void err_tcp(void *arg,err_t err)
753 u32 dummy = 0;
754 struct netconn *conn = (struct netconn*)arg;
756 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: err_tcp: %d\n",err));
757 if(conn) {
758 conn->err = err;
759 conn->pcb.tcp = NULL;
760 if(conn->recvmbox!=SYS_MBOX_NULL) {
761 if(conn->callback) (*conn->callback)(conn,NETCONN_EVTRCVPLUS,0);
762 MQ_Send(conn->recvmbox,&dummy,MQ_MSG_BLOCK);
764 if(conn->mbox!=SYS_MBOX_NULL) {
765 MQ_Send(conn->mbox,&dummy,MQ_MSG_BLOCK);
767 if(conn->acceptmbox!=SYS_MBOX_NULL) {
768 if(conn->callback) (*conn->callback)(conn,NETCONN_EVTRCVPLUS,0);
769 MQ_Send(conn->acceptmbox,&dummy,MQ_MSG_BLOCK);
771 if(conn->sem!=SYS_SEM_NULL) {
772 LWP_SemPost(conn->sem);
777 static err_t poll_tcp(void *arg,struct tcp_pcb *pcb)
779 struct netconn *conn = (struct netconn*)arg;
781 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: poll_tcp\n"));
782 if(conn && conn->sem!=SYS_SEM_NULL && (conn->state==NETCONN_WRITE || conn->state==NETCONN_CLOSE))
783 LWP_SemPost(conn->sem);
785 return ERR_OK;
788 static err_t sent_tcp(void *arg,struct tcp_pcb *pcb,u16 len)
790 struct netconn *conn = (struct netconn*)arg;
792 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: sent_tcp: sent %d bytes\n",len));
793 if(conn && conn->sem!=SYS_SEM_NULL)
794 LWP_SemPost(conn->sem);
796 if(conn && conn->callback) {
797 if(tcp_sndbuf(conn->pcb.tcp)>TCP_SNDLOWAT)
798 (*conn->callback)(conn,NETCONN_EVTSENDPLUS,len);
800 return ERR_OK;
803 static void setuptcp(struct netconn *conn)
805 struct tcp_pcb *pcb = conn->pcb.tcp;
807 tcp_arg(pcb,conn);
808 tcp_recv(pcb,recv_tcp);
809 tcp_sent(pcb,sent_tcp);
810 tcp_poll(pcb,poll_tcp,4);
811 tcp_err(pcb,err_tcp);
814 static err_t accept_func(void *arg,struct tcp_pcb *newpcb,err_t err)
816 sys_mbox mbox;
817 struct netconn *newconn,*conn = (struct netconn*)arg;
819 LWIP_DEBUGF(API_LIB_DEBUG, ("accept_func: %p %p %d\n",arg,newpcb,err));
821 mbox = conn->acceptmbox;
822 newconn = memp_malloc(MEMP_NETCONN);
823 if(newconn==NULL) return ERR_MEM;
825 if(MQ_Init(&newconn->recvmbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) {
826 memp_free(MEMP_NETCONN,newconn);
827 return ERR_MEM;
830 if(MQ_Init(&newconn->mbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) {
831 MQ_Close(newconn->recvmbox);
832 memp_free(MEMP_NETCONN,newconn);
833 return ERR_MEM;
836 if(LWP_SemInit(&newconn->sem,0,1)==-1) {
837 MQ_Close(newconn->recvmbox);
838 MQ_Close(newconn->mbox);
839 memp_free(MEMP_NETCONN,newconn);
840 return ERR_MEM;
843 newconn->type = NETCONN_TCP;
844 newconn->pcb.tcp = newpcb;
845 setuptcp(newconn);
847 newconn->acceptmbox = SYS_MBOX_NULL;
848 newconn->err = err;
850 if(conn->callback) {
851 (*conn->callback)(conn,NETCONN_EVTRCVPLUS,0);
853 newconn->callback = conn->callback;
854 newconn->socket = -1;
855 newconn->recvavail = 0;
857 MQ_Send(mbox,&newconn,MQ_MSG_BLOCK);
858 return ERR_OK;
861 static void do_newconn(struct apimsg_msg *msg)
863 u32 dummy = 0;
865 if(msg->conn->pcb.tcp) {
866 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
867 return;
870 msg->conn->err = ERR_OK;
871 switch(msg->conn->type) {
872 case NETCONN_RAW:
873 msg->conn->pcb.raw = raw_new(msg->msg.bc.port);
874 raw_recv(msg->conn->pcb.raw,recv_raw,msg->conn);
875 break;
876 case NETCONN_UDPLITE:
877 msg->conn->pcb.udp = udp_new();
878 if(!msg->conn->pcb.udp) {
879 msg->conn->err = ERR_MEM;
880 break;
882 udp_setflags(msg->conn->pcb.udp,UDP_FLAGS_UDPLITE);
883 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
884 break;
885 case NETCONN_UDPNOCHKSUM:
886 msg->conn->pcb.udp = udp_new();
887 if(!msg->conn->pcb.udp) {
888 msg->conn->err = ERR_MEM;
889 break;
891 udp_setflags(msg->conn->pcb.udp,UDP_FLAGS_NOCHKSUM);
892 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
893 break;
894 case NETCONN_UDP:
895 msg->conn->pcb.udp = udp_new();
896 if(!msg->conn->pcb.udp) {
897 msg->conn->err = ERR_MEM;
898 break;
900 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
901 break;
902 case NETCONN_TCP:
903 msg->conn->pcb.tcp = tcp_new();
904 if(!msg->conn->pcb.tcp) {
905 msg->conn->err = ERR_MEM;
906 break;
908 setuptcp(msg->conn);
909 break;
910 default:
911 break;
913 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
916 static void do_delconn(struct apimsg_msg *msg)
918 u32 dummy = 0;
920 if(msg->conn->pcb.tcp) {
921 switch(msg->conn->type) {
922 case NETCONN_RAW:
923 raw_remove(msg->conn->pcb.raw);
924 break;
925 case NETCONN_UDPLITE:
926 case NETCONN_UDPNOCHKSUM:
927 case NETCONN_UDP:
928 msg->conn->pcb.udp->recv_arg = NULL;
929 udp_remove(msg->conn->pcb.udp);
930 break;
931 case NETCONN_TCP:
932 if(msg->conn->pcb.tcp->state==LISTEN) {
933 tcp_arg(msg->conn->pcb.tcp,NULL);
934 tcp_accept(msg->conn->pcb.tcp,NULL);
935 tcp_close(msg->conn->pcb.tcp);
936 } else {
937 tcp_arg(msg->conn->pcb.tcp,NULL);
938 tcp_sent(msg->conn->pcb.tcp,NULL);
939 tcp_recv(msg->conn->pcb.tcp,NULL);
940 tcp_poll(msg->conn->pcb.tcp,NULL,0);
941 tcp_err(msg->conn->pcb.tcp,NULL);
942 if(tcp_close(msg->conn->pcb.tcp)!=ERR_OK)
943 tcp_abort(msg->conn->pcb.tcp);
945 break;
946 default:
947 break;
950 if(msg->conn->callback) {
951 (*msg->conn->callback)(msg->conn,NETCONN_EVTRCVPLUS,0);
952 (*msg->conn->callback)(msg->conn,NETCONN_EVTSENDPLUS,0);
954 if(msg->conn->mbox!=SYS_MBOX_NULL)
955 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
958 static void do_bind(struct apimsg_msg *msg)
960 u32 dummy = 0;
962 if(msg->conn->pcb.tcp==NULL) {
963 switch(msg->conn->type) {
964 case NETCONN_RAW:
965 msg->conn->pcb.raw = raw_new(msg->msg.bc.port);
966 raw_recv(msg->conn->pcb.raw,recv_raw,msg->conn);
967 break;
968 case NETCONN_UDPLITE:
969 msg->conn->pcb.udp = udp_new();
970 udp_setflags(msg->conn->pcb.udp,UDP_FLAGS_UDPLITE);
971 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
972 break;
973 case NETCONN_UDPNOCHKSUM:
974 msg->conn->pcb.udp = udp_new();
975 udp_setflags(msg->conn->pcb.udp,UDP_FLAGS_NOCHKSUM);
976 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
977 break;
978 case NETCONN_UDP:
979 msg->conn->pcb.udp = udp_new();
980 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
981 break;
982 case NETCONN_TCP:
983 msg->conn->pcb.tcp = tcp_new();
984 setuptcp(msg->conn);
985 break;
986 default:
987 break;
990 switch(msg->conn->type) {
991 case NETCONN_RAW:
992 msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);
993 break;
994 case NETCONN_UDPLITE:
995 case NETCONN_UDPNOCHKSUM:
996 case NETCONN_UDP:
997 msg->conn->err = udp_bind(msg->conn->pcb.udp,msg->msg.bc.ipaddr,msg->msg.bc.port);
998 break;
999 case NETCONN_TCP:
1000 msg->conn->err = tcp_bind(msg->conn->pcb.tcp,msg->msg.bc.ipaddr,msg->msg.bc.port);
1001 break;
1002 default:
1003 break;
1005 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1008 static err_t do_connected(void *arg,struct tcp_pcb *pcb,err_t err)
1010 u32 dummy = 0;
1011 struct netconn *conn = (struct netconn*)arg;
1013 if(!conn) return ERR_VAL;
1015 conn->err = err;
1016 if(conn->type==NETCONN_TCP && err==ERR_OK) setuptcp(conn);
1018 MQ_Send(conn->mbox,&dummy,MQ_MSG_BLOCK);
1019 return ERR_OK;
1022 static void do_connect(struct apimsg_msg *msg)
1024 u32 dummy = 0;
1026 if(!msg->conn->pcb.tcp) {
1027 switch(msg->conn->type) {
1028 case NETCONN_RAW:
1029 msg->conn->pcb.raw = raw_new(msg->msg.bc.port);
1030 raw_recv(msg->conn->pcb.raw,recv_raw,msg->conn);
1031 break;
1032 case NETCONN_UDPLITE:
1033 msg->conn->pcb.udp = udp_new();
1034 if(!msg->conn->pcb.udp) {
1035 msg->conn->err = ERR_MEM;
1036 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1037 return;
1039 udp_setflags(msg->conn->pcb.udp,UDP_FLAGS_UDPLITE);
1040 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
1041 break;
1042 case NETCONN_UDPNOCHKSUM:
1043 msg->conn->pcb.udp = udp_new();
1044 if(!msg->conn->pcb.udp) {
1045 msg->conn->err = ERR_MEM;
1046 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1047 return;
1049 udp_setflags(msg->conn->pcb.udp,UDP_FLAGS_NOCHKSUM);
1050 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
1051 break;
1052 case NETCONN_UDP:
1053 msg->conn->pcb.udp = udp_new();
1054 if(!msg->conn->pcb.udp) {
1055 msg->conn->err = ERR_MEM;
1056 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1057 return;
1059 udp_recv(msg->conn->pcb.udp,recv_udp,msg->conn);
1060 break;
1061 case NETCONN_TCP:
1062 msg->conn->pcb.tcp = tcp_new();
1063 if(!msg->conn->pcb.tcp) {
1064 msg->conn->err = ERR_MEM;
1065 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1066 return;
1068 break;
1069 default:
1070 break;
1073 switch(msg->conn->type) {
1074 case NETCONN_RAW:
1075 raw_connect(msg->conn->pcb.raw,msg->msg.bc.ipaddr);
1076 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1077 break;
1078 case NETCONN_UDPLITE:
1079 case NETCONN_UDPNOCHKSUM:
1080 case NETCONN_UDP:
1081 udp_connect(msg->conn->pcb.udp,msg->msg.bc.ipaddr,msg->msg.bc.port);
1082 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1083 break;
1084 case NETCONN_TCP:
1085 setuptcp(msg->conn);
1086 tcp_connect(msg->conn->pcb.tcp,msg->msg.bc.ipaddr,msg->msg.bc.port,do_connected);
1087 break;
1088 default:
1089 break;
1093 static void do_disconnect(struct apimsg_msg *msg)
1095 u32 dummy = 0;
1097 switch(msg->conn->type) {
1098 case NETCONN_RAW:
1099 break;
1100 case NETCONN_UDPLITE:
1101 case NETCONN_UDPNOCHKSUM:
1102 case NETCONN_UDP:
1103 udp_disconnect(msg->conn->pcb.udp);
1104 break;
1105 case NETCONN_TCP:
1106 break;
1108 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1111 static void do_listen(struct apimsg_msg *msg)
1113 u32 dummy = 0;
1115 if(msg->conn->pcb.tcp!=NULL) {
1116 switch(msg->conn->type) {
1117 case NETCONN_RAW:
1118 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n"));
1119 break;
1120 case NETCONN_UDPLITE:
1121 case NETCONN_UDPNOCHKSUM:
1122 case NETCONN_UDP:
1123 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n"));
1124 break;
1125 case NETCONN_TCP:
1126 msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp);
1127 if(msg->conn->pcb.tcp==NULL)
1128 msg->conn->err = ERR_MEM;
1129 else {
1130 if(msg->conn->acceptmbox==SYS_MBOX_NULL) {
1131 if(MQ_Init(&msg->conn->acceptmbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) {
1132 msg->conn->err = ERR_MEM;
1133 break;
1136 tcp_arg(msg->conn->pcb.tcp,msg->conn);
1137 tcp_accept(msg->conn->pcb.tcp,accept_func);
1139 break;
1140 default:
1141 break;
1144 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1147 static void do_accept(struct apimsg_msg *msg)
1149 if(msg->conn->pcb.tcp) {
1150 switch(msg->conn->type) {
1151 case NETCONN_RAW:
1152 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n"));
1153 break;
1154 case NETCONN_UDPLITE:
1155 case NETCONN_UDPNOCHKSUM:
1156 case NETCONN_UDP:
1157 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n"));
1158 break;
1159 case NETCONN_TCP:
1160 break;
1165 static void do_send(struct apimsg_msg *msg)
1167 u32 dummy = 0;
1169 if(msg->conn->pcb.tcp) {
1170 switch(msg->conn->type) {
1171 case NETCONN_RAW:
1172 raw_send(msg->conn->pcb.raw,msg->msg.p);
1173 break;
1174 case NETCONN_UDPLITE:
1175 case NETCONN_UDPNOCHKSUM:
1176 case NETCONN_UDP:
1177 udp_send(msg->conn->pcb.udp,msg->msg.p);
1178 break;
1179 case NETCONN_TCP:
1180 break;
1183 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1186 static void do_recv(struct apimsg_msg *msg)
1188 u32 dummy = 0;
1190 if(msg->conn->pcb.tcp && msg->conn->type==NETCONN_TCP) {
1191 tcp_recved(msg->conn->pcb.tcp,msg->msg.len);
1193 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1196 static void do_write(struct apimsg_msg *msg)
1198 err_t err;
1199 u32 dummy = 0;
1201 if(msg->conn->pcb.tcp) {
1202 switch(msg->conn->type) {
1203 case NETCONN_RAW:
1204 case NETCONN_UDPLITE:
1205 case NETCONN_UDPNOCHKSUM:
1206 case NETCONN_UDP:
1207 msg->conn->err = ERR_VAL;
1208 break;
1209 case NETCONN_TCP:
1210 err = tcp_write(msg->conn->pcb.tcp,msg->msg.w.dataptr,msg->msg.w.len,msg->msg.w.copy);
1211 if(err==ERR_OK && (!msg->conn->pcb.tcp->unacked || (msg->conn->pcb.tcp->flags&TF_NODELAY)
1212 || msg->conn->pcb.tcp->snd_queuelen>1)) {
1213 LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: TCP write: tcp_output.\n"));
1214 tcp_output(msg->conn->pcb.tcp);
1216 msg->conn->err = err;
1217 if(msg->conn->callback) {
1218 if(err==ERR_OK) {
1219 if(tcp_sndbuf(msg->conn->pcb.tcp)<=TCP_SNDLOWAT)
1220 (*msg->conn->callback)(msg->conn,NETCONN_EVTSENDMINUS,msg->msg.w.len);
1223 break;
1224 default:
1225 break;
1228 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1231 static void do_close(struct apimsg_msg *msg)
1233 u32 dummy = 0;
1234 err_t err = ERR_OK;
1236 if(msg->conn->pcb.tcp) {
1237 switch(msg->conn->type) {
1238 case NETCONN_RAW:
1239 case NETCONN_UDPLITE:
1240 case NETCONN_UDPNOCHKSUM:
1241 case NETCONN_UDP:
1242 break;
1243 case NETCONN_TCP:
1244 if(msg->conn->pcb.tcp->state==LISTEN)
1245 err = tcp_close(msg->conn->pcb.tcp);
1246 else if(msg->conn->pcb.tcp->state==CLOSE_WAIT)
1247 err = tcp_output(msg->conn->pcb.tcp);
1248 msg->conn->err = err;
1249 break;
1250 default:
1251 break;
1254 MQ_Send(msg->conn->mbox,&dummy,MQ_MSG_BLOCK);
1257 static void apimsg_input(struct api_msg *msg)
1259 decode[msg->type](&(msg->msg));
1262 static void apimsg_post(struct api_msg *msg)
1264 net_apimsg(msg);
1267 /* tcpip thread part */
1268 static err_t net_input(struct pbuf *p,struct netif *inp)
1270 struct net_msg *msg = memp_malloc(MEMP_TCPIP_MSG);
1272 LWIP_DEBUGF(TCPIP_DEBUG, ("net_input: %p %p\n", p,inp));
1274 if(msg==NULL) {
1275 LWIP_ERROR(("net_input: msg out of memory.\n"));
1276 pbuf_free(p);
1277 return ERR_MEM;
1280 msg->type = NETMSG_INPUT;
1281 msg->msg.inp.p = p;
1282 msg->msg.inp.net = inp;
1283 MQ_Send(netthread_mbox,&msg,MQ_MSG_BLOCK);
1284 return ERR_OK;
1287 static void net_apimsg(struct api_msg *apimsg)
1289 struct net_msg *msg = memp_malloc(MEMP_TCPIP_MSG);
1291 LWIP_DEBUGF(TCPIP_DEBUG, ("net_apimsg: %p\n",apimsg));
1292 if(msg==NULL) {
1293 LWIP_ERROR(("net_apimsg: msg out of memory.\n"));
1294 memp_free(MEMP_API_MSG,apimsg);
1295 return;
1298 msg->type = NETMSG_API;
1299 msg->msg.apimsg = apimsg;
1300 MQ_Send(netthread_mbox,&msg,MQ_MSG_BLOCK);
1303 static err_t net_callback(void (*f)(void *),void *ctx)
1305 struct net_msg *msg = memp_malloc(MEMP_TCPIP_MSG);
1307 LWIP_DEBUGF(TCPIP_DEBUG, ("net_callback: %p(%p)\n", f,ctx));
1309 if(msg==NULL) {
1310 LWIP_ERROR(("net_apimsg: msg out of memory.\n"));
1311 return ERR_MEM;
1314 msg->type = NETMSG_CALLBACK;
1315 msg->msg.cb.f = f;
1316 msg->msg.cb.ctx = ctx;
1317 MQ_Send(netthread_mbox,&msg,MQ_MSG_BLOCK);
1318 return ERR_OK;
1321 static void* net_thread(void *arg)
1323 struct net_msg *msg;
1324 struct timespec tb;
1325 sys_sem sem = (sys_sem)arg;
1327 etharp_init();
1328 ip_init();
1329 udp_init();
1330 tcp_init();
1333 tb.tv_sec = ARP_TMR_INTERVAL/TB_MSPERSEC;
1334 tb.tv_nsec = 0;
1335 net_arp_ticks = __lwp_wd_calc_ticks(&tb);
1336 __lwp_wd_initialize(&arp_time_cntrl,__arp_timer,ARP_TIMER_ID,NULL);
1337 __lwp_wd_insert_ticks(&arp_time_cntrl,net_arp_ticks);
1339 tb.tv_sec = 0;
1340 tb.tv_nsec = TCP_TMR_INTERVAL*TB_NSPERMS;
1341 net_tcp_ticks = __lwp_wd_calc_ticks(&tb);
1342 __lwp_wd_initialize(&tcp_timer_cntrl,__tcp_timer,TCP_TIMER_ID,NULL);
1344 LWP_SemPost(sem);
1346 LWIP_DEBUGF(TCPIP_DEBUG, ("net_thread(%p)\n",arg));
1348 while(1) {
1349 MQ_Receive(netthread_mbox,(mqmsg_t)&msg,MQ_MSG_BLOCK);
1350 switch(msg->type) {
1351 case NETMSG_API:
1352 LWIP_DEBUGF(TCPIP_DEBUG, ("net_thread: API message %p\n", (void *)msg));
1353 apimsg_input(msg->msg.apimsg);
1354 break;
1355 case NETMSG_INPUT:
1356 LWIP_DEBUGF(TCPIP_DEBUG, ("net_thread: IP packet %p\n", (void *)msg));
1357 bba_process(msg->msg.inp.p,msg->msg.inp.net);
1358 break;
1359 case NETMSG_CALLBACK:
1360 LWIP_DEBUGF(TCPIP_DEBUG, ("net_thread: CALLBACK %p\n", (void *)msg));
1361 msg->msg.cb.f(msg->msg.cb.ctx);
1362 break;
1363 default:
1364 break;
1366 memp_free(MEMP_TCPIP_MSG,msg);
1370 /* sockets part */
1371 static s32 alloc_socket(struct netconn *conn)
1373 s32 i;
1375 LWP_SemWait(netsocket_sem);
1377 for(i=0;i<NUM_SOCKETS;i++) {
1378 if(!sockets[i].conn) {
1379 sockets[i].conn = conn;
1380 sockets[i].lastdata = NULL;
1381 sockets[i].lastoffset = 0;
1382 sockets[i].rcvevt = 0;
1383 sockets[i].sendevt = 1;
1384 sockets[i].flags = 0;
1385 sockets[i].err = 0;
1386 LWP_SemPost(netsocket_sem);
1387 return i;
1391 LWP_SemPost(netsocket_sem);
1392 return -1;
1395 static struct netsocket* get_socket(s32 s)
1397 struct netsocket *sock;
1398 if(s<0 || s>NUM_SOCKETS) {
1399 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
1400 return NULL;
1402 sock = &sockets[s];
1403 if(!sock->conn) {
1404 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): no active\n", s));
1405 return NULL;
1408 return sock;
1411 static void evt_callback(struct netconn *conn,enum netconn_evt evt,u32 len)
1413 s32 s;
1414 struct netsocket *sock;
1415 struct netselect_cb *scb;
1417 if(conn) {
1418 s = conn->socket;
1419 if(s<0) {
1420 if(evt==NETCONN_EVTRCVPLUS)
1421 conn->socket--;
1422 return;
1424 sock = get_socket(s);
1425 if(!sock) return;
1426 } else
1427 return;
1429 LWP_SemWait(sockselect_sem);
1430 switch(evt) {
1431 case NETCONN_EVTRCVPLUS:
1432 sock->rcvevt++;
1433 break;
1434 case NETCONN_EVTRCVMINUS:
1435 sock->rcvevt--;
1436 break;
1437 case NETCONN_EVTSENDPLUS:
1438 sock->sendevt = 1;
1439 break;
1440 case NETCONN_EVTSENDMINUS:
1441 sock->sendevt = 0;
1442 break;
1444 LWP_SemPost(sockselect_sem);
1446 while(1) {
1447 LWP_SemWait(sockselect_sem);
1448 for(scb = selectcb_list;scb;scb = scb->next) {
1449 if(scb->signaled==0) {
1450 if(scb->readset && FD_ISSET(s,scb->readset))
1451 if(sock->rcvevt) break;
1452 if(scb->writeset && FD_ISSET(s,scb->writeset))
1453 if(sock->sendevt) break;
1456 if(scb) {
1457 scb->signaled = 1;
1458 LWP_SemPost(sockselect_sem);
1459 LWP_MutexLock(scb->cond_lck);
1460 LWP_CondSignal(scb->cond);
1461 LWP_MutexUnlock(scb->cond_lck);
1462 } else {
1463 LWP_SemPost(sockselect_sem);
1464 break;
1470 extern const devoptab_t dotab_stdnet;
1472 s32 if_configex(struct in_addr *local_ip,struct in_addr *netmask,struct in_addr *gateway,boolean use_dhcp)
1474 s32 ret = 0;
1475 struct ip_addr loc_ip, mask, gw;
1476 struct netif *pnet;
1477 struct timespec tb;
1478 dev_s hbba = NULL;
1480 if(g_netinitiated) return 0;
1481 g_netinitiated = 1;
1483 AddDevice(&dotab_stdnet);
1484 #ifdef STATS
1485 stats_init();
1486 #endif /* STATS */
1488 sys_init();
1489 mem_init();
1490 memp_init();
1491 pbuf_init();
1492 netif_init();
1494 // init tcpip thread message box
1495 if(MQ_Init(&netthread_mbox,MQBOX_SIZE)!=MQ_ERROR_SUCCESSFUL) return -1;
1497 // create & setup interface
1498 loc_ip.addr = 0;
1499 mask.addr = 0;
1500 gw.addr = 0;
1503 if(use_dhcp==FALSE) {
1504 if( !gateway || gateway->s_addr==0
1505 || !local_ip || local_ip->s_addr==0
1506 || !netmask || netmask->s_addr==0 ) return -1;
1507 loc_ip.addr = local_ip->s_addr;
1508 mask.addr = netmask->s_addr;
1509 gw.addr = gateway->s_addr;
1511 hbba = bba_create(&g_hNetIF);
1512 pnet = netif_add(&g_hNetIF,&loc_ip, &mask, &gw, hbba, bba_init, net_input);
1513 if(pnet) {
1514 netif_set_up(pnet);
1515 netif_set_default(pnet);
1516 #if (LWIP_DHCP)
1517 if(use_dhcp==TRUE) {
1518 //setup coarse timer
1519 tb.tv_sec = DHCP_COARSE_TIMER_SECS;
1520 tb.tv_nsec = 0;
1521 net_dhcpcoarse_ticks = __lwp_wd_calc_ticks(&tb);
1522 __lwp_wd_initialize(&dhcp_coarsetimer_cntrl,__dhcpcoarse_timer,DHCPCOARSE_TIMER_ID,NULL);
1523 __lwp_wd_insert_ticks(&dhcp_coarsetimer_cntrl,net_dhcpcoarse_ticks);
1525 //setup fine timer
1526 tb.tv_sec = 0;
1527 tb.tv_nsec = DHCP_FINE_TIMER_MSECS*TB_NSPERMS;
1528 net_dhcpfine_ticks = __lwp_wd_calc_ticks(&tb);
1529 __lwp_wd_initialize(&dhcp_finetimer_cntrl,__dhcpfine_timer,DHCPFINE_TIMER_ID,NULL);
1530 __lwp_wd_insert_ticks(&dhcp_finetimer_cntrl,net_dhcpfine_ticks);
1532 //now start dhcp client
1533 dhcp_start(pnet);
1535 #endif
1536 } else
1537 return -1;
1539 // setup loopinterface
1540 IP4_ADDR(&loc_ip, 127,0,0,1);
1541 IP4_ADDR(&mask, 255,0,0,0);
1542 IP4_ADDR(&gw, 127,0,0,1);
1543 pnet = netif_add(&g_hLoopIF,&loc_ip,&mask,&gw,NULL,loopif_init,net_input);
1545 //last and least start the tcpip layer
1546 ret = net_init();
1548 if ( ret == 0 && use_dhcp == TRUE ) {
1550 int retries = 0;
1551 // wait for dhcp to bind
1552 while ( g_hNetIF.dhcp->state != DHCP_BOUND && retries < 20 ) {
1553 retries++;
1554 usleep(500000);
1557 if ( retries < 20 ) {
1558 //copy back network addresses
1559 if ( local_ip != NULL ) local_ip->s_addr = g_hNetIF.ip_addr.addr;
1560 if ( gateway != NULL ) gateway->s_addr = g_hNetIF.gw.addr;
1561 if ( netmask != NULL ) netmask->s_addr = g_hNetIF.netmask.addr;
1562 } else {
1563 ret = -2;
1567 return ret;
1570 s32 if_config(char *local_ip, char *netmask, char *gateway,boolean use_dhcp)
1572 s32 ret = 0;
1573 struct in_addr loc_ip, mask, gw;
1575 loc_ip.s_addr = 0;
1576 mask.s_addr = 0;
1577 gw.s_addr = 0;
1579 if ( local_ip != NULL ) loc_ip.s_addr = inet_addr(local_ip);
1580 if ( netmask != NULL ) mask.s_addr = inet_addr(netmask);
1581 if ( gateway != NULL ) gw.s_addr = inet_addr(gateway);
1583 ret = if_configex( &loc_ip, &mask, &gw, use_dhcp );
1585 if (ret<0) return ret;
1587 if ( use_dhcp == TRUE ) {
1588 //copy back network addresses
1589 if ( local_ip != NULL ) strcpy(local_ip, inet_ntoa( loc_ip ));
1590 if ( netmask != NULL ) strcpy(netmask, inet_ntoa( mask));
1591 if ( gateway != NULL ) strcpy(gateway, inet_ntoa( gw ));
1593 return ret;
1597 s32 net_init()
1599 sys_sem sem;
1601 if(tcpiplayer_inited) return 1;
1603 if(LWP_SemInit(&netsocket_sem,1,1)==-1) return -1;
1604 if(LWP_SemInit(&sockselect_sem,1,1)==-1) {
1605 LWP_SemDestroy(netsocket_sem);
1606 return -1;
1608 if(LWP_SemInit(&sem,0,1)==-1) {
1609 LWP_SemDestroy(netsocket_sem);
1610 LWP_SemDestroy(sockselect_sem);
1611 return -1;
1614 if(LWP_CreateThread(&hnet_thread,net_thread,(void*)sem,netthread_stack,STACKSIZE,220)==-1) {
1615 LWP_SemDestroy(netsocket_sem);
1616 LWP_SemDestroy(sockselect_sem);
1617 LWP_SemDestroy(sem);
1618 return -1;
1620 LWP_SemWait(sem);
1621 LWP_SemDestroy(sem);
1623 tcpiplayer_inited = 1;
1625 return 0;
1628 s32 net_shutdown(s32 s,u32 how)
1630 return -1;
1633 s32 net_fcntl(s32 s, u32 cmd, u32 flags)
1635 return -1;
1638 s32 net_socket(u32 domain,u32 type,u32 protocol)
1640 s32 i;
1641 struct netconn *conn;
1643 switch(type) {
1644 case SOCK_RAW:
1645 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_socket(SOCK_RAW)\n"));
1646 conn = netconn_new_with_proto_and_callback(NETCONN_RAW,protocol,evt_callback);
1647 break;
1648 case SOCK_DGRAM:
1649 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_socket(SOCK_DGRAM)\n"));
1650 conn = netconn_new_with_callback(NETCONN_UDP,evt_callback);
1651 break;
1652 case SOCK_STREAM:
1653 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_socket(SOCK_STREAM)\n"));
1654 conn = netconn_new_with_callback(NETCONN_TCP,evt_callback);
1655 break;
1656 default:
1657 return -1;
1659 if(!conn) return -1;
1661 i = alloc_socket(conn);
1662 if(i==-1) {
1663 netconn_delete(conn);
1664 return -1;
1667 conn->socket = i;
1668 return i;
1671 s32 net_accept(s32 s,struct sockaddr *addr,socklen_t *addrlen)
1673 struct netsocket *sock;
1674 struct netconn *newconn;
1675 struct ip_addr naddr = {0};
1676 u16 port = 0;
1677 s32 newsock;
1678 struct sockaddr_in sin;
1680 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_accept(%d)\n", s));
1682 sock = get_socket(s);
1683 if(!sock) return -1;
1685 newconn = netconn_accept(sock->conn);
1686 netconn_peer(newconn,&naddr,&port);
1688 memset(&sin,0,sizeof(sin));
1689 sin.sin_family = AF_INET;
1690 sin.sin_port = htons(port);
1691 sin.sin_addr.s_addr = naddr.addr;
1693 if(*addrlen>sizeof(sin))
1694 *addrlen = sizeof(sin);
1695 memcpy(addr,&sin,*addrlen);
1697 newsock = alloc_socket(newconn);
1698 if(newsock==-1) {
1699 netconn_delete(newconn);
1700 return -1;
1703 newconn->callback = evt_callback;
1704 sock = get_socket(newsock);
1706 LWP_SemWait(netsocket_sem);
1707 sock->rcvevt += -1 - newconn->socket;
1708 newconn->socket = newsock;
1709 LWP_SemPost(netsocket_sem);
1711 return newsock;
1714 s32 net_bind(s32 s,struct sockaddr *name,socklen_t namelen)
1716 struct netsocket *sock;
1717 struct ip_addr loc_addr;
1718 u16 loc_port;
1719 err_t err;
1721 sock = get_socket(s);
1722 if(!sock) return -1;
1724 loc_addr.addr = ((struct sockaddr_in*)name)->sin_addr.s_addr;
1725 loc_port = ((struct sockaddr_in*)name)->sin_port;
1727 err = netconn_bind(sock->conn,&loc_addr,ntohs(loc_port));
1728 if(err!=ERR_OK) return -1;
1730 return 0;
1733 s32 net_listen(s32 s,u32 backlog)
1735 struct netsocket *sock;
1736 err_t err;
1738 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_listen(%d, backlog=%d)\n", s, backlog));
1739 sock = get_socket(s);
1740 if(!sock) return -1;
1742 err = netconn_listen(sock->conn);
1743 if(err!=ERR_OK) {
1744 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_listen(%d) failed, err=%d\n", s, err));
1745 return -1;
1747 return 0;
1750 s32 net_recvfrom(s32 s,void *mem,s32 len,u32 flags,struct sockaddr *from,socklen_t *fromlen)
1752 struct netsocket *sock;
1753 struct netbuf *buf;
1754 u16 buflen,copylen;
1755 struct ip_addr *addr;
1756 u16 port;
1758 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
1759 if(mem==NULL || len<=0) return -1;
1761 sock = get_socket(s);
1762 if(!sock) return -1;
1764 if(sock->lastdata)
1765 buf = sock->lastdata;
1766 else {
1767 if(((flags&MSG_DONTWAIT) || (sock->flags&O_NONBLOCK)) && !sock->rcvevt) {
1768 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_recvfrom(%d): returning EWOULDBLOCK\n", s));
1769 return -1;
1771 buf = netconn_recv(sock->conn);
1772 if(!buf) {
1773 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_recvfrom(%d): buf == NULL!\n", s));
1774 return 0;
1778 buflen = netbuf_len(buf);
1779 buflen -= sock->lastoffset;
1780 if(buflen<=0)
1781 return 0;
1782 if(len>buflen)
1783 copylen = buflen;
1784 else
1785 copylen = len;
1787 netbuf_copypartial(buf,mem,copylen,sock->lastoffset);
1789 if(from && fromlen) {
1790 struct sockaddr_in sin;
1792 addr = netbuf_fromaddr(buf);
1793 port = netbuf_fromport(buf);
1795 memset(&sin,0,sizeof(sin));
1796 sin.sin_family = AF_INET;
1797 sin.sin_port = htons(port);
1798 sin.sin_addr.s_addr = addr->addr;
1800 if(*fromlen>sizeof(sin))
1801 *fromlen = sizeof(sin);
1803 memcpy(from,&sin,*fromlen);
1805 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_recvfrom(%d): addr=", s));
1806 ip_addr_debug_print(SOCKETS_DEBUG, addr);
1807 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
1809 if(netconn_type(sock->conn)==NETCONN_TCP && (buflen-copylen)>0) {
1810 sock->lastdata = buf;
1811 sock->lastoffset += copylen;
1812 } else {
1813 sock->lastdata = NULL;
1814 sock->lastoffset = 0;
1815 netbuf_delete(buf);
1817 return copylen;
1820 s32 net_read(s32 s,void *mem,s32 len)
1822 return net_recvfrom(s,mem,len,0,NULL,NULL);
1825 s32 net_recv(s32 s,void *mem,s32 len,u32 flags)
1827 return net_recvfrom(s,mem,len,flags,NULL,NULL);
1830 s32 net_sendto(s32 s,const void *data,s32 len,u32 flags,struct sockaddr *to,socklen_t tolen)
1832 struct netsocket *sock;
1833 struct ip_addr remote_addr, addr;
1834 u16_t remote_port, port = 0;
1835 s32 ret,connected;
1837 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_sendto(%d, data=%p, size=%d, flags=0x%x)\n", s, data, len, flags));
1838 if(data==NULL || len<=0) return -1;
1840 sock = get_socket(s);
1841 if (!sock) return -1;
1843 /* get the peer if currently connected */
1844 connected = (netconn_peer(sock->conn, &addr, &port) == ERR_OK);
1846 remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
1847 remote_port = ((struct sockaddr_in *)to)->sin_port;
1849 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, len, flags));
1850 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
1851 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port)));
1853 netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
1855 ret = net_send(s, data, len, flags);
1857 /* reset the remote address and port number
1858 of the connection */
1859 if (connected)
1860 netconn_connect(sock->conn, &addr, port);
1861 else
1862 netconn_disconnect(sock->conn);
1863 return ret;
1866 s32 net_send(s32 s,const void *data,s32 len,u32 flags)
1868 struct netsocket *sock;
1869 struct netbuf *buf;
1870 err_t err;
1872 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, len, flags));
1873 if(data==NULL || len<=0) return -1;
1875 sock = get_socket(s);
1876 if(!sock) return -1;
1878 switch(netconn_type(sock->conn)) {
1879 case NETCONN_RAW:
1880 case NETCONN_UDP:
1881 case NETCONN_UDPLITE:
1882 case NETCONN_UDPNOCHKSUM:
1883 buf = netbuf_new();
1884 if(!buf) {
1885 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_send(%d) ENOBUFS\n", s));
1886 return -1;
1888 netbuf_ref(buf,data,len);
1889 err = netconn_send(sock->conn,buf);
1890 netbuf_delete(buf);
1891 break;
1892 case NETCONN_TCP:
1893 err = netconn_write(sock->conn,data,len,NETCONN_COPY);
1894 break;
1895 default:
1896 err = ERR_ARG;
1897 break;
1899 if(err!=ERR_OK) {
1900 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_send(%d) err=%d\n", s, err));
1901 return -1;
1904 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_send(%d) ok size=%d\n", s, len));
1905 return len;
1908 s32 net_write(s32 s,const void *data,s32 size)
1910 return net_send(s,data,size,0);
1913 s32 net_connect(s32 s,struct sockaddr *name,socklen_t namelen)
1915 struct netsocket *sock;
1916 err_t err;
1918 sock = get_socket(s);
1919 if(!sock) return -1;
1921 if(((struct sockaddr_in*)name)->sin_family==AF_UNSPEC) {
1922 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_connect(%d, AF_UNSPEC)\n", s));
1923 err = netconn_disconnect(sock->conn);
1924 } else {
1925 struct ip_addr remote_addr;
1926 u16 remote_port;
1928 remote_addr.addr = ((struct sockaddr_in*)name)->sin_addr.s_addr;
1929 remote_port = ((struct sockaddr_in*)name)->sin_port;
1931 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_connect(%d, addr=", s));
1932 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
1933 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));
1935 err = netconn_connect(sock->conn,&remote_addr,ntohs(remote_port));
1937 if(err!=ERR_OK) {
1938 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_connect(%d) failed, err=%d\n", s, err));
1939 return -1;
1942 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_connect(%d) succeeded\n", s));
1943 return 0;
1946 s32 net_close(s32 s)
1948 struct netsocket *sock;
1950 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_close(%d)\n", s));
1952 LWP_SemWait(netsocket_sem);
1954 sock = get_socket(s);
1955 if(!sock) {
1956 LWP_SemPost(netsocket_sem);
1957 return -1;
1960 netconn_delete(sock->conn);
1961 if(sock->lastdata) netbuf_delete(sock->lastdata);
1963 sock->lastdata = NULL;
1964 sock->lastoffset = 0;
1965 sock->conn = NULL;
1967 LWP_SemPost(netsocket_sem);
1968 return 0;
1971 static s32 net_selscan(s32 maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset)
1973 s32 i,nready = 0;
1974 fd_set lreadset,lwriteset,lexceptset;
1975 struct netsocket *sock;
1977 FD_ZERO(&lreadset);
1978 FD_ZERO(&lwriteset);
1979 FD_ZERO(&lexceptset);
1981 for(i=0;i<maxfdp1;i++) {
1982 if(FD_ISSET(i,readset)) {
1983 sock = get_socket(i);
1984 if(sock && (sock->lastdata || sock->rcvevt)) {
1985 FD_SET(i,&lreadset);
1986 nready++;
1989 if(FD_ISSET(i,writeset)) {
1990 sock = get_socket(i);
1991 if(sock && sock->sendevt) {
1992 FD_SET(i,&lwriteset);
1993 nready++;
1997 *readset = lreadset;
1998 *writeset = lwriteset;
1999 FD_ZERO(exceptset);
2001 return nready;
2004 s32 net_select(s32 maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,struct timeval *timeout)
2006 s32 i,nready;
2007 fd_set lreadset,lwriteset,lexceptset;
2008 struct timespec tb,*p_tb;
2009 struct netselect_cb sel_cb;
2010 struct netselect_cb *psel_cb;
2012 sel_cb.next = NULL;
2013 sel_cb.readset = readset;
2014 sel_cb.writeset = writeset;
2015 sel_cb.exceptset = exceptset;
2016 sel_cb.signaled = 0;
2018 LWP_SemWait(sockselect_sem);
2020 if(readset)
2021 lreadset = *readset;
2022 else
2023 FD_ZERO(&lreadset);
2025 if(writeset)
2026 lwriteset = *writeset;
2027 else
2028 FD_ZERO(&lwriteset);
2030 if(exceptset)
2031 lexceptset = *exceptset;
2032 else
2033 FD_ZERO(&lexceptset);
2035 nready = net_selscan(maxfdp1,&lreadset,&lwriteset,&lexceptset);
2036 if(!nready) {
2037 if(timeout && timeout->tv_sec==0 && timeout->tv_usec==0) {
2038 LWP_SemPost(sockselect_sem);
2039 if(readset)
2040 FD_ZERO(readset);
2041 if(writeset)
2042 FD_ZERO(writeset);
2043 if(exceptset)
2044 FD_ZERO(exceptset);
2045 return 0;
2048 LWP_MutexInit(&sel_cb.cond_lck,FALSE);
2049 LWP_CondInit(&sel_cb.cond);
2050 sel_cb.next = selectcb_list;
2051 selectcb_list = &sel_cb;
2053 LWP_SemPost(sockselect_sem);
2054 if(timeout==NULL)
2055 p_tb = NULL;
2056 else {
2057 tb.tv_sec = timeout->tv_sec;
2058 tb.tv_nsec = (timeout->tv_usec+500)*TB_NSPERUS;
2059 p_tb = &tb;
2062 LWP_MutexLock(sel_cb.cond_lck);
2063 i = LWP_CondTimedWait(sel_cb.cond,sel_cb.cond_lck,p_tb);
2064 LWP_MutexUnlock(sel_cb.cond_lck);
2066 LWP_SemWait(sockselect_sem);
2067 if(selectcb_list==&sel_cb)
2068 selectcb_list = sel_cb.next;
2069 else {
2070 for(psel_cb = selectcb_list;psel_cb;psel_cb = psel_cb->next) {
2071 if(psel_cb->next==&sel_cb) {
2072 psel_cb->next = sel_cb.next;
2073 break;
2077 LWP_CondDestroy(sel_cb.cond);
2078 LWP_MutexDestroy(sel_cb.cond_lck);
2080 LWP_SemPost(sockselect_sem);
2082 if(i==ETIMEDOUT) {
2083 if(readset)
2084 FD_ZERO(readset);
2085 if(writeset)
2086 FD_ZERO(writeset);
2087 if(exceptset)
2088 FD_ZERO(exceptset);
2089 return 0;
2092 if(readset)
2093 lreadset = *readset;
2094 else
2095 FD_ZERO(&lreadset);
2097 if(writeset)
2098 lwriteset = *writeset;
2099 else
2100 FD_ZERO(&lwriteset);
2102 if(exceptset)
2103 lexceptset = *exceptset;
2104 else
2105 FD_ZERO(&lexceptset);
2107 nready = net_selscan(maxfdp1,&lreadset,&lwriteset,&lexceptset);
2108 } else
2109 LWP_SemPost(sockselect_sem);
2111 if(readset)
2112 *readset = lreadset;
2113 if(writeset)
2114 *writeset = lwriteset;
2115 if(exceptset)
2116 *exceptset = lexceptset;
2118 return nready;
2121 s32 net_setsockopt(s32 s,u32 level,u32 optname,const void *optval,socklen_t optlen)
2123 s32 err = 0;
2124 struct netsocket *sock;
2126 sock = get_socket(s);
2127 if(sock==NULL) return -1;
2128 if(optval==NULL) return -1;
2130 switch(level) {
2131 case SOL_SOCKET:
2133 switch(optname) {
2134 case SO_BROADCAST:
2135 case SO_KEEPALIVE:
2136 case SO_REUSEADDR:
2137 case SO_REUSEPORT:
2138 if(optlen<sizeof(u32)) err = EINVAL;
2139 break;
2140 default:
2141 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
2142 err = ENOPROTOOPT;
2145 break;
2147 case IPPROTO_IP:
2149 switch(optname) {
2150 case IP_TTL:
2151 case IP_TOS:
2152 if(optlen<sizeof(u32)) err = EINVAL;
2153 break;
2154 default:
2155 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
2156 err = ENOPROTOOPT;
2159 break;
2161 case IPPROTO_TCP:
2163 if(optlen<sizeof(u32)) {
2164 err = EINVAL;
2165 break;
2167 if(sock->conn->type!=NETCONN_TCP) return 0;
2169 switch(optname) {
2170 case TCP_NODELAY:
2171 case TCP_KEEPALIVE:
2172 break;
2173 default:
2174 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
2175 err = ENOPROTOOPT;
2178 break;
2180 default:
2181 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
2182 err = ENOPROTOOPT;
2184 if(err!=0) return -1;
2186 switch(level) {
2187 case SOL_SOCKET:
2189 switch(optname) {
2190 case SO_BROADCAST:
2191 case SO_KEEPALIVE:
2192 case SO_REUSEADDR:
2193 case SO_REUSEPORT:
2194 if(*(u32*)optval)
2195 sock->conn->pcb.tcp->so_options |= optname;
2196 else
2197 sock->conn->pcb.tcp->so_options &= ~optname;
2198 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(u32*)optval?"on":"off")));
2199 break;
2202 break;
2204 case IPPROTO_IP:
2206 switch(optname) {
2207 case IP_TTL:
2208 sock->conn->pcb.tcp->ttl = (u8)(*(u32*)optval);
2209 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %u\n", s, sock->conn->pcb.tcp->ttl));
2210 break;
2211 case IP_TOS:
2212 sock->conn->pcb.tcp->tos = (u8)(*(u32*)optval);
2213 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n", s, sock->conn->pcb.tcp->tos));
2214 break;
2217 break;
2219 case IPPROTO_TCP:
2221 switch(optname) {
2222 case TCP_NODELAY:
2223 if(*(u32*)optval)
2224 sock->conn->pcb.tcp->flags |= TF_NODELAY;
2225 else
2226 sock->conn->pcb.tcp->flags &= ~TF_NODELAY;
2227 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", s, (*(u32*)optval)?"on":"off") );
2228 break;
2229 case TCP_KEEPALIVE:
2230 sock->conn->pcb.tcp->keepalive = (u32)(*(u32*)optval);
2231 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %u\n", s, sock->conn->pcb.tcp->keepalive));
2232 break;
2236 return err?-1:0;
2239 s32 net_ioctl(s32 s, u32 cmd, void *argp)
2241 struct netsocket *sock = get_socket(s);
2243 if(!sock) return -1;
2245 switch (cmd) {
2246 case FIONREAD:
2247 if(!argp) return -1;
2249 *((u16_t*)argp) = sock->conn->recvavail;
2251 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16*)argp)));
2252 return 0;
2254 case FIONBIO:
2255 if(argp && *(u32*)argp)
2256 sock->flags |= O_NONBLOCK;
2257 else
2258 sock->flags &= ~O_NONBLOCK;
2259 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags&O_NONBLOCK)));
2260 return 0;
2262 default:
2263 LWIP_DEBUGF(SOCKETS_DEBUG, ("net_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
2264 return -1;