Warning, cross-references for /kernel/lwip/api/api_msg.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 #include "lwip/opt.h"
0040
0041 #if LWIP_NETCONN
0042
0043 #include "lwip/api_msg.h"
0044
0045 #include "lwip/ip.h"
0046 #include "lwip/udp.h"
0047 #include "lwip/tcp.h"
0048 #include "lwip/raw.h"
0049
0050 #include "lwip/memp.h"
0051 #include "lwip/tcpip.h"
0052 #include "lwip/igmp.h"
0053 #include "lwip/dns.h"
0054
0055 #include <string.h>
0056
0057
0058 #if LWIP_TCP
0059 static err_t do_writemore(struct netconn *conn);
0060 static void do_close_internal(struct netconn *conn);
0061 #endif
0062
0063 #if LWIP_RAW
0064
0065
0066
0067
0068
0069
0070
0071 static u8_t
0072 recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
0073 struct ip_addr *addr)
0074 {
0075 struct pbuf *q;
0076 struct netbuf *buf;
0077 struct netconn *conn;
0078 #if LWIP_SO_RCVBUF
0079 int recv_avail;
0080 #endif
0081
0082 LWIP_UNUSED_ARG(addr);
0083 conn = arg;
0084
0085 #if LWIP_SO_RCVBUF
0086 SYS_ARCH_GET(conn->recv_avail, recv_avail);
0087 if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL) &&
0088 ((recv_avail + (int)(p->tot_len)) <= conn->recv_bufsize)) {
0089 #else
0090 if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL)) {
0091 #endif
0092
0093 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
0094 if(q != NULL) {
0095 if (pbuf_copy(q, p) != ERR_OK) {
0096 pbuf_free(q);
0097 q = NULL;
0098 }
0099 }
0100
0101 if(q != NULL) {
0102 buf = memp_malloc(MEMP_NETBUF);
0103 if (buf == NULL) {
0104 pbuf_free(q);
0105 return 0;
0106 }
0107
0108 buf->p = q;
0109 buf->ptr = q;
0110 buf->addr = &(((struct ip_hdr*)(q->payload))->src);
0111 buf->port = pcb->protocol;
0112
0113 if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
0114 netbuf_delete(buf);
0115 return 0;
0116 } else {
0117 SYS_ARCH_INC(conn->recv_avail, q->tot_len);
0118
0119 API_EVENT(conn, NETCONN_EVT_RCVPLUS, q->tot_len);
0120 }
0121 }
0122 }
0123
0124 return 0;
0125 }
0126 #endif
0127
0128 #if LWIP_UDP
0129
0130
0131
0132
0133
0134
0135 static void
0136 recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
0137 struct ip_addr *addr, u16_t port)
0138 {
0139 struct netbuf *buf;
0140 struct netconn *conn;
0141 #if LWIP_SO_RCVBUF
0142 int recv_avail;
0143 #endif
0144
0145 LWIP_UNUSED_ARG(pcb);
0146 LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
0147 LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
0148 conn = arg;
0149 LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
0150
0151 #if LWIP_SO_RCVBUF
0152 SYS_ARCH_GET(conn->recv_avail, recv_avail);
0153 if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL) ||
0154 ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
0155 #else
0156 if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) {
0157 #endif
0158 pbuf_free(p);
0159 return;
0160 }
0161
0162 buf = memp_malloc(MEMP_NETBUF);
0163 if (buf == NULL) {
0164 pbuf_free(p);
0165 return;
0166 } else {
0167 buf->p = p;
0168 buf->ptr = p;
0169 buf->addr = addr;
0170 buf->port = port;
0171 #if LWIP_NETBUF_RECVINFO
0172 {
0173 const struct ip_hdr* iphdr = ip_current_header();
0174
0175 const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr));
0176 buf->toaddr = (struct ip_addr*)&iphdr->dest;
0177 buf->toport = udphdr->dest;
0178 }
0179 #endif
0180 }
0181
0182 if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
0183 netbuf_delete(buf);
0184 return;
0185 } else {
0186 SYS_ARCH_INC(conn->recv_avail, p->tot_len);
0187
0188 API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
0189 }
0190 }
0191 #endif
0192
0193 #if LWIP_TCP
0194
0195
0196
0197
0198
0199
0200 static err_t
0201 recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
0202 {
0203 struct netconn *conn;
0204 u16_t len;
0205
0206 LWIP_UNUSED_ARG(pcb);
0207 LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL);
0208 LWIP_ASSERT("recv_tcp must have an argument", arg != NULL);
0209 conn = arg;
0210 LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb);
0211
0212 if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) {
0213 return ERR_VAL;
0214 }
0215
0216 conn->err = err;
0217 if (p != NULL) {
0218 len = p->tot_len;
0219 SYS_ARCH_INC(conn->recv_avail, len);
0220 } else {
0221 len = 0;
0222 }
0223
0224 if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) {
0225 return ERR_MEM;
0226 } else {
0227
0228 API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
0229 }
0230
0231 return ERR_OK;
0232 }
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245 static err_t
0246 poll_tcp(void *arg, struct tcp_pcb *pcb)
0247 {
0248 struct netconn *conn = arg;
0249
0250 LWIP_UNUSED_ARG(pcb);
0251 LWIP_ASSERT("conn != NULL", (conn != NULL));
0252
0253 if (conn->state == NETCONN_WRITE) {
0254 do_writemore(conn);
0255 } else if (conn->state == NETCONN_CLOSE) {
0256 do_close_internal(conn);
0257 }
0258
0259 return ERR_OK;
0260 }
0261
0262
0263
0264
0265
0266
0267
0268
0269 static err_t
0270 sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
0271 {
0272 struct netconn *conn = arg;
0273
0274 LWIP_UNUSED_ARG(pcb);
0275 LWIP_ASSERT("conn != NULL", (conn != NULL));
0276
0277 if (conn->state == NETCONN_WRITE) {
0278 LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL);
0279 do_writemore(conn);
0280 } else if (conn->state == NETCONN_CLOSE) {
0281 do_close_internal(conn);
0282 }
0283
0284 if (conn) {
0285 if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)) {
0286 API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
0287 }
0288 }
0289
0290 return ERR_OK;
0291 }
0292
0293
0294
0295
0296
0297
0298
0299
0300 static void
0301 err_tcp(void *arg, err_t err)
0302 {
0303 struct netconn *conn;
0304
0305 conn = arg;
0306 LWIP_ASSERT("conn != NULL", (conn != NULL));
0307
0308 conn->pcb.tcp = NULL;
0309
0310 conn->err = err;
0311 if (conn->recvmbox != SYS_MBOX_NULL) {
0312
0313 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
0314 sys_mbox_post(conn->recvmbox, NULL);
0315 }
0316 if (conn->op_completed != SYS_SEM_NULL && conn->state == NETCONN_CONNECT) {
0317 conn->state = NETCONN_NONE;
0318 sys_sem_signal(conn->op_completed);
0319 }
0320 if (conn->acceptmbox != SYS_MBOX_NULL) {
0321
0322 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
0323 sys_mbox_post(conn->acceptmbox, NULL);
0324 }
0325 if ((conn->state == NETCONN_WRITE) || (conn->state == NETCONN_CLOSE)) {
0326
0327
0328 conn->state = NETCONN_NONE;
0329
0330 sys_sem_signal(conn->op_completed);
0331 }
0332 }
0333
0334
0335
0336
0337
0338
0339
0340 static void
0341 setup_tcp(struct netconn *conn)
0342 {
0343 struct tcp_pcb *pcb;
0344
0345 pcb = conn->pcb.tcp;
0346 tcp_arg(pcb, conn);
0347 tcp_recv(pcb, recv_tcp);
0348 tcp_sent(pcb, sent_tcp);
0349 tcp_poll(pcb, poll_tcp, 4);
0350 tcp_err(pcb, err_tcp);
0351 }
0352
0353
0354
0355
0356
0357
0358
0359 static err_t
0360 accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
0361 {
0362 struct netconn *newconn;
0363 struct netconn *conn;
0364
0365 #if API_MSG_DEBUG
0366 #if TCP_DEBUG
0367 tcp_debug_print_state(newpcb->state);
0368 #endif
0369 #endif
0370 conn = (struct netconn *)arg;
0371
0372 LWIP_ERROR("accept_function: invalid conn->acceptmbox",
0373 conn->acceptmbox != SYS_MBOX_NULL, return ERR_VAL;);
0374
0375
0376
0377 newconn = netconn_alloc(conn->type, conn->callback);
0378 if (newconn == NULL) {
0379 return ERR_MEM;
0380 }
0381 newconn->pcb.tcp = newpcb;
0382 setup_tcp(newconn);
0383 newconn->err = err;
0384
0385 if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) {
0386
0387
0388 newconn->pcb.tcp = NULL;
0389 netconn_free(newconn);
0390 return ERR_MEM;
0391 } else {
0392
0393 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
0394 }
0395
0396 return ERR_OK;
0397 }
0398 #endif
0399
0400
0401
0402
0403
0404
0405
0406
0407 static err_t
0408 pcb_new(struct api_msg_msg *msg)
0409 {
0410 msg->conn->err = ERR_OK;
0411
0412 LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
0413
0414
0415 switch(NETCONNTYPE_GROUP(msg->conn->type)) {
0416 #if LWIP_RAW
0417 case NETCONN_RAW:
0418 msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
0419 if(msg->conn->pcb.raw == NULL) {
0420 msg->conn->err = ERR_MEM;
0421 break;
0422 }
0423 raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
0424 break;
0425 #endif
0426 #if LWIP_UDP
0427 case NETCONN_UDP:
0428 msg->conn->pcb.udp = udp_new();
0429 if(msg->conn->pcb.udp == NULL) {
0430 msg->conn->err = ERR_MEM;
0431 break;
0432 }
0433 #if LWIP_UDPLITE
0434 if (msg->conn->type==NETCONN_UDPLITE) {
0435 udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
0436 }
0437 #endif
0438 if (msg->conn->type==NETCONN_UDPNOCHKSUM) {
0439 udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
0440 }
0441 udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
0442 break;
0443 #endif
0444 #if LWIP_TCP
0445 case NETCONN_TCP:
0446 msg->conn->pcb.tcp = tcp_new();
0447 if(msg->conn->pcb.tcp == NULL) {
0448 msg->conn->err = ERR_MEM;
0449 break;
0450 }
0451 setup_tcp(msg->conn);
0452 break;
0453 #endif
0454 default:
0455
0456 msg->conn->err = ERR_VAL;
0457 break;
0458 }
0459
0460 return msg->conn->err;
0461 }
0462
0463
0464
0465
0466
0467
0468
0469 void
0470 do_newconn(struct api_msg_msg *msg)
0471 {
0472 if(msg->conn->pcb.tcp == NULL) {
0473 pcb_new(msg);
0474 }
0475
0476
0477
0478
0479 TCPIP_APIMSG_ACK(msg);
0480 }
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492 struct netconn*
0493 netconn_alloc(enum netconn_type t, netconn_callback callback)
0494 {
0495 struct netconn *conn;
0496 int size;
0497
0498 conn = memp_malloc(MEMP_NETCONN);
0499 if (conn == NULL) {
0500 return NULL;
0501 }
0502
0503 conn->err = ERR_OK;
0504 conn->type = t;
0505 conn->pcb.tcp = NULL;
0506
0507 #if (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_UDP_RECVMBOX_SIZE) && \
0508 (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_TCP_RECVMBOX_SIZE)
0509 size = DEFAULT_RAW_RECVMBOX_SIZE;
0510 #else
0511 switch(NETCONNTYPE_GROUP(t)) {
0512 #if LWIP_RAW
0513 case NETCONN_RAW:
0514 size = DEFAULT_RAW_RECVMBOX_SIZE;
0515 break;
0516 #endif
0517 #if LWIP_UDP
0518 case NETCONN_UDP:
0519 size = DEFAULT_UDP_RECVMBOX_SIZE;
0520 break;
0521 #endif
0522 #if LWIP_TCP
0523 case NETCONN_TCP:
0524 size = DEFAULT_TCP_RECVMBOX_SIZE;
0525 break;
0526 #endif
0527 default:
0528 LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0);
0529 break;
0530 }
0531 #endif
0532
0533 if ((conn->op_completed = sys_sem_new(0)) == SYS_SEM_NULL) {
0534 memp_free(MEMP_NETCONN, conn);
0535 return NULL;
0536 }
0537 if ((conn->recvmbox = sys_mbox_new(size)) == SYS_MBOX_NULL) {
0538 sys_sem_free(conn->op_completed);
0539 memp_free(MEMP_NETCONN, conn);
0540 return NULL;
0541 }
0542
0543 conn->acceptmbox = SYS_MBOX_NULL;
0544 conn->state = NETCONN_NONE;
0545
0546 conn->socket = -1;
0547 conn->callback = callback;
0548 conn->recv_avail = 0;
0549 #if LWIP_TCP
0550 conn->write_msg = NULL;
0551 conn->write_offset = 0;
0552 #if LWIP_TCPIP_CORE_LOCKING
0553 conn->write_delayed = 0;
0554 #endif
0555 #endif
0556 #if LWIP_SO_RCVTIMEO
0557 conn->recv_timeout = 0;
0558 #endif
0559 #if LWIP_SO_RCVBUF
0560 conn->recv_bufsize = RECV_BUFSIZE_DEFAULT;
0561 #endif
0562 return conn;
0563 }
0564
0565
0566
0567
0568
0569
0570
0571 void
0572 netconn_free(struct netconn *conn)
0573 {
0574 void *mem;
0575 LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL);
0576
0577
0578 if (conn->recvmbox != SYS_MBOX_NULL) {
0579 while (sys_mbox_tryfetch(conn->recvmbox, &mem) != SYS_MBOX_EMPTY) {
0580 if (conn->type == NETCONN_TCP) {
0581 if(mem != NULL) {
0582 pbuf_free((struct pbuf *)mem);
0583 }
0584 } else {
0585 netbuf_delete((struct netbuf *)mem);
0586 }
0587 }
0588 sys_mbox_free(conn->recvmbox);
0589 conn->recvmbox = SYS_MBOX_NULL;
0590 }
0591
0592
0593 if (conn->acceptmbox != SYS_MBOX_NULL) {
0594 while (sys_mbox_tryfetch(conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) {
0595 netconn_delete((struct netconn *)mem);
0596 }
0597 sys_mbox_free(conn->acceptmbox);
0598 conn->acceptmbox = SYS_MBOX_NULL;
0599 }
0600
0601 sys_sem_free(conn->op_completed);
0602 conn->op_completed = SYS_SEM_NULL;
0603
0604 memp_free(MEMP_NETCONN, conn);
0605 }
0606
0607 #if LWIP_TCP
0608
0609
0610
0611
0612
0613
0614
0615 static void
0616 do_close_internal(struct netconn *conn)
0617 {
0618 err_t err;
0619
0620 LWIP_ASSERT("invalid conn", (conn != NULL));
0621 LWIP_ASSERT("this is for tcp netconns only", (conn->type == NETCONN_TCP));
0622 LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE));
0623 LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
0624
0625
0626 tcp_arg(conn->pcb.tcp, NULL);
0627 if (conn->pcb.tcp->state == LISTEN) {
0628 tcp_accept(conn->pcb.tcp, NULL);
0629 } else {
0630 tcp_recv(conn->pcb.tcp, NULL);
0631 tcp_accept(conn->pcb.tcp, NULL);
0632
0633 tcp_sent(conn->pcb.tcp, NULL);
0634 tcp_poll(conn->pcb.tcp, NULL, 4);
0635 tcp_err(conn->pcb.tcp, NULL);
0636 }
0637
0638 err = tcp_close(conn->pcb.tcp);
0639 if (err == ERR_OK) {
0640
0641 conn->state = NETCONN_NONE;
0642
0643 conn->pcb.tcp = NULL;
0644 conn->err = ERR_OK;
0645
0646
0647 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
0648 API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
0649
0650 sys_sem_signal(conn->op_completed);
0651 } else {
0652
0653
0654 LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN));
0655 tcp_sent(conn->pcb.tcp, sent_tcp);
0656 tcp_poll(conn->pcb.tcp, poll_tcp, 4);
0657 tcp_err(conn->pcb.tcp, err_tcp);
0658 tcp_arg(conn->pcb.tcp, conn);
0659 }
0660
0661
0662 }
0663 #endif
0664
0665
0666
0667
0668
0669
0670
0671 void
0672 do_delconn(struct api_msg_msg *msg)
0673 {
0674 if (msg->conn->pcb.tcp != NULL) {
0675 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
0676 #if LWIP_RAW
0677 case NETCONN_RAW:
0678 raw_remove(msg->conn->pcb.raw);
0679 break;
0680 #endif
0681 #if LWIP_UDP
0682 case NETCONN_UDP:
0683 msg->conn->pcb.udp->recv_arg = NULL;
0684 udp_remove(msg->conn->pcb.udp);
0685 break;
0686 #endif
0687 #if LWIP_TCP
0688 case NETCONN_TCP:
0689 msg->conn->state = NETCONN_CLOSE;
0690 do_close_internal(msg->conn);
0691
0692
0693 return;
0694 #endif
0695 default:
0696 break;
0697 }
0698 }
0699
0700
0701
0702
0703 API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0);
0704 API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0);
0705
0706 if (msg->conn->op_completed != SYS_SEM_NULL) {
0707 sys_sem_signal(msg->conn->op_completed);
0708 }
0709 }
0710
0711
0712
0713
0714
0715
0716
0717
0718 void
0719 do_bind(struct api_msg_msg *msg)
0720 {
0721 if (!ERR_IS_FATAL(msg->conn->err)) {
0722 if (msg->conn->pcb.tcp != NULL) {
0723 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
0724 #if LWIP_RAW
0725 case NETCONN_RAW:
0726 msg->conn->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
0727 break;
0728 #endif
0729 #if LWIP_UDP
0730 case NETCONN_UDP:
0731 msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
0732 break;
0733 #endif
0734 #if LWIP_TCP
0735 case NETCONN_TCP:
0736 msg->conn->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port);
0737 break;
0738 #endif
0739 default:
0740 break;
0741 }
0742 } else {
0743
0744 msg->conn->err = ERR_VAL;
0745 }
0746 }
0747 TCPIP_APIMSG_ACK(msg);
0748 }
0749
0750 #if LWIP_TCP
0751
0752
0753
0754
0755
0756
0757 static err_t
0758 do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
0759 {
0760 struct netconn *conn;
0761
0762 LWIP_UNUSED_ARG(pcb);
0763
0764 conn = arg;
0765
0766 if (conn == NULL) {
0767 return ERR_VAL;
0768 }
0769
0770 conn->err = err;
0771 if ((conn->type == NETCONN_TCP) && (err == ERR_OK)) {
0772 setup_tcp(conn);
0773 }
0774 conn->state = NETCONN_NONE;
0775 sys_sem_signal(conn->op_completed);
0776 return ERR_OK;
0777 }
0778 #endif
0779
0780
0781
0782
0783
0784
0785
0786
0787 void
0788 do_connect(struct api_msg_msg *msg)
0789 {
0790 if (msg->conn->pcb.tcp == NULL) {
0791 sys_sem_signal(msg->conn->op_completed);
0792 return;
0793 }
0794
0795 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
0796 #if LWIP_RAW
0797 case NETCONN_RAW:
0798 msg->conn->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
0799 sys_sem_signal(msg->conn->op_completed);
0800 break;
0801 #endif
0802 #if LWIP_UDP
0803 case NETCONN_UDP:
0804 msg->conn->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
0805 sys_sem_signal(msg->conn->op_completed);
0806 break;
0807 #endif
0808 #if LWIP_TCP
0809 case NETCONN_TCP:
0810 msg->conn->state = NETCONN_CONNECT;
0811 setup_tcp(msg->conn);
0812 msg->conn->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,
0813 do_connected);
0814
0815
0816 break;
0817 #endif
0818 default:
0819 LWIP_ERROR("Invalid netconn type", 0, do{ msg->conn->err = ERR_VAL;
0820 sys_sem_signal(msg->conn->op_completed); }while(0));
0821 break;
0822 }
0823 }
0824
0825
0826
0827
0828
0829
0830
0831
0832 void
0833 do_disconnect(struct api_msg_msg *msg)
0834 {
0835 #if LWIP_UDP
0836 if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
0837 udp_disconnect(msg->conn->pcb.udp);
0838 }
0839 #endif
0840 TCPIP_APIMSG_ACK(msg);
0841 }
0842
0843
0844
0845
0846
0847
0848
0849 void
0850 do_listen(struct api_msg_msg *msg)
0851 {
0852 #if LWIP_TCP
0853 if (!ERR_IS_FATAL(msg->conn->err)) {
0854 if (msg->conn->pcb.tcp != NULL) {
0855 if (msg->conn->type == NETCONN_TCP) {
0856 if (msg->conn->pcb.tcp->state == CLOSED) {
0857 #if TCP_LISTEN_BACKLOG
0858 struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
0859 #else
0860 struct tcp_pcb* lpcb = tcp_listen(msg->conn->pcb.tcp);
0861 #endif
0862 if (lpcb == NULL) {
0863 msg->conn->err = ERR_MEM;
0864 } else {
0865
0866 if (msg->conn->recvmbox != SYS_MBOX_NULL) {
0867
0868 sys_mbox_free(msg->conn->recvmbox);
0869 msg->conn->recvmbox = SYS_MBOX_NULL;
0870 }
0871 if (msg->conn->acceptmbox == SYS_MBOX_NULL) {
0872 if ((msg->conn->acceptmbox = sys_mbox_new(DEFAULT_ACCEPTMBOX_SIZE)) == SYS_MBOX_NULL) {
0873 msg->conn->err = ERR_MEM;
0874 }
0875 }
0876 if (msg->conn->err == ERR_OK) {
0877 msg->conn->state = NETCONN_LISTEN;
0878 msg->conn->pcb.tcp = lpcb;
0879 tcp_arg(msg->conn->pcb.tcp, msg->conn);
0880 tcp_accept(msg->conn->pcb.tcp, accept_function);
0881 }
0882 }
0883 } else {
0884 msg->conn->err = ERR_CONN;
0885 }
0886 }
0887 }
0888 }
0889 #endif
0890 TCPIP_APIMSG_ACK(msg);
0891 }
0892
0893
0894
0895
0896
0897
0898
0899 void
0900 do_send(struct api_msg_msg *msg)
0901 {
0902 if (!ERR_IS_FATAL(msg->conn->err)) {
0903 if (msg->conn->pcb.tcp != NULL) {
0904 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
0905 #if LWIP_RAW
0906 case NETCONN_RAW:
0907 if (msg->msg.b->addr == NULL) {
0908 msg->conn->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
0909 } else {
0910 msg->conn->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, msg->msg.b->addr);
0911 }
0912 break;
0913 #endif
0914 #if LWIP_UDP
0915 case NETCONN_UDP:
0916 if (msg->msg.b->addr == NULL) {
0917 msg->conn->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
0918 } else {
0919 msg->conn->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, msg->msg.b->addr, msg->msg.b->port);
0920 }
0921 break;
0922 #endif
0923 default:
0924 break;
0925 }
0926 }
0927 }
0928 TCPIP_APIMSG_ACK(msg);
0929 }
0930
0931
0932
0933
0934
0935
0936
0937 void
0938 do_recv(struct api_msg_msg *msg)
0939 {
0940 #if LWIP_TCP
0941 if (!ERR_IS_FATAL(msg->conn->err)) {
0942 if (msg->conn->pcb.tcp != NULL) {
0943 if (msg->conn->type == NETCONN_TCP) {
0944 #if TCP_LISTEN_BACKLOG
0945 if (msg->conn->pcb.tcp->state == LISTEN) {
0946 tcp_accepted(msg->conn->pcb.tcp);
0947 } else
0948 #endif
0949 {
0950 tcp_recved(msg->conn->pcb.tcp, msg->msg.r.len);
0951 }
0952 }
0953 }
0954 }
0955 #endif
0956 TCPIP_APIMSG_ACK(msg);
0957 }
0958
0959 #if LWIP_TCP
0960
0961
0962
0963
0964
0965
0966
0967
0968
0969
0970
0971 static err_t
0972 do_writemore(struct netconn *conn)
0973 {
0974 err_t err;
0975 void *dataptr;
0976 u16_t len, available;
0977 u8_t write_finished = 0;
0978 size_t diff;
0979
0980 LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE));
0981
0982 dataptr = (u8_t*)conn->write_msg->msg.w.dataptr + conn->write_offset;
0983 diff = conn->write_msg->msg.w.len - conn->write_offset;
0984 if (diff > 0xffffUL) {
0985 len = 0xffff;
0986 #if LWIP_TCPIP_CORE_LOCKING
0987 conn->write_delayed = 1;
0988 #endif
0989 } else {
0990 len = (u16_t)diff;
0991 }
0992 available = tcp_sndbuf(conn->pcb.tcp);
0993 if (available < len) {
0994
0995 len = available;
0996 #if LWIP_TCPIP_CORE_LOCKING
0997 conn->write_delayed = 1;
0998 #endif
0999 }
1000
1001 err = tcp_write(conn->pcb.tcp, dataptr, len, conn->write_msg->msg.w.apiflags);
1002 LWIP_ASSERT("do_writemore: invalid length!", ((conn->write_offset + len) <= conn->write_msg->msg.w.len));
1003 if (err == ERR_OK) {
1004 conn->write_offset += len;
1005 if (conn->write_offset == conn->write_msg->msg.w.len) {
1006
1007 write_finished = 1;
1008 conn->write_msg = NULL;
1009 conn->write_offset = 0;
1010
1011 conn->state = NETCONN_NONE;
1012 }
1013 err = tcp_output_nagle(conn->pcb.tcp);
1014 conn->err = err;
1015 if ((err == ERR_OK) && (tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT)) {
1016 API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
1017 }
1018 } else if (err == ERR_MEM) {
1019
1020
1021
1022
1023
1024 err = tcp_output(conn->pcb.tcp);
1025
1026 #if LWIP_TCPIP_CORE_LOCKING
1027 conn->write_delayed = 1;
1028 #endif
1029 } else {
1030
1031
1032 conn->err = err;
1033 write_finished = 1;
1034 }
1035
1036 if (write_finished) {
1037
1038
1039 conn->state = NETCONN_NONE;
1040 #if LWIP_TCPIP_CORE_LOCKING
1041 if (conn->write_delayed != 0)
1042 #endif
1043 {
1044 sys_sem_signal(conn->op_completed);
1045 }
1046 }
1047 #if LWIP_TCPIP_CORE_LOCKING
1048 else
1049 return ERR_MEM;
1050 #endif
1051 return ERR_OK;
1052 }
1053 #endif
1054
1055
1056
1057
1058
1059
1060
1061 void
1062 do_write(struct api_msg_msg *msg)
1063 {
1064 if (!ERR_IS_FATAL(msg->conn->err)) {
1065 if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
1066 #if LWIP_TCP
1067 msg->conn->state = NETCONN_WRITE;
1068
1069 LWIP_ASSERT("already writing", msg->conn->write_msg == NULL &&
1070 msg->conn->write_offset == 0);
1071 msg->conn->write_msg = msg;
1072 msg->conn->write_offset = 0;
1073 #if LWIP_TCPIP_CORE_LOCKING
1074 msg->conn->write_delayed = 0;
1075 if (do_writemore(msg->conn) != ERR_OK) {
1076 LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE);
1077 UNLOCK_TCPIP_CORE();
1078 sys_arch_sem_wait(msg->conn->op_completed, 0);
1079 LOCK_TCPIP_CORE();
1080 LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE);
1081 }
1082 #else
1083 do_writemore(msg->conn);
1084 #endif
1085
1086 return;
1087 #endif
1088 #if (LWIP_UDP || LWIP_RAW)
1089 } else {
1090 msg->conn->err = ERR_VAL;
1091 #endif
1092 }
1093 }
1094 TCPIP_APIMSG_ACK(msg);
1095 }
1096
1097
1098
1099
1100
1101
1102
1103 void
1104 do_getaddr(struct api_msg_msg *msg)
1105 {
1106 if (msg->conn->pcb.ip != NULL) {
1107 *(msg->msg.ad.ipaddr) = (msg->msg.ad.local?msg->conn->pcb.ip->local_ip:msg->conn->pcb.ip->remote_ip);
1108
1109 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
1110 #if LWIP_RAW
1111 case NETCONN_RAW:
1112 if (msg->msg.ad.local) {
1113 *(msg->msg.ad.port) = msg->conn->pcb.raw->protocol;
1114 } else {
1115
1116 msg->conn->err = ERR_CONN;
1117 }
1118 break;
1119 #endif
1120 #if LWIP_UDP
1121 case NETCONN_UDP:
1122 if (msg->msg.ad.local) {
1123 *(msg->msg.ad.port) = msg->conn->pcb.udp->local_port;
1124 } else {
1125 if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) {
1126 msg->conn->err = ERR_CONN;
1127 } else {
1128 *(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port;
1129 }
1130 }
1131 break;
1132 #endif
1133 #if LWIP_TCP
1134 case NETCONN_TCP:
1135 *(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port);
1136 break;
1137 #endif
1138 }
1139 } else {
1140 msg->conn->err = ERR_CONN;
1141 }
1142 TCPIP_APIMSG_ACK(msg);
1143 }
1144
1145
1146
1147
1148
1149
1150
1151 void
1152 do_close(struct api_msg_msg *msg)
1153 {
1154 #if LWIP_TCP
1155 if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
1156 msg->conn->state = NETCONN_CLOSE;
1157 do_close_internal(msg->conn);
1158
1159 } else
1160 #endif
1161 {
1162 msg->conn->err = ERR_VAL;
1163 sys_sem_signal(msg->conn->op_completed);
1164 }
1165 }
1166
1167 #if LWIP_IGMP
1168
1169
1170
1171
1172
1173
1174 void
1175 do_join_leave_group(struct api_msg_msg *msg)
1176 {
1177 if (!ERR_IS_FATAL(msg->conn->err)) {
1178 if (msg->conn->pcb.tcp != NULL) {
1179 if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
1180 #if LWIP_UDP
1181 if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
1182 msg->conn->err = igmp_joingroup(msg->msg.jl.interface, msg->msg.jl.multiaddr);
1183 } else {
1184 msg->conn->err = igmp_leavegroup(msg->msg.jl.interface, msg->msg.jl.multiaddr);
1185 }
1186 #endif
1187 #if (LWIP_TCP || LWIP_RAW)
1188 } else {
1189 msg->conn->err = ERR_VAL;
1190 #endif
1191 }
1192 }
1193 }
1194 TCPIP_APIMSG_ACK(msg);
1195 }
1196 #endif
1197
1198 #if LWIP_DNS
1199
1200
1201
1202
1203
1204 static void
1205 do_dns_found(const char *name, struct ip_addr *ipaddr, void *arg)
1206 {
1207 struct dns_api_msg *msg = (struct dns_api_msg*)arg;
1208
1209 LWIP_ASSERT("DNS response for wrong host name", strcmp(msg->name, name) == 0);
1210
1211 if (ipaddr == NULL) {
1212
1213 *msg->err = ERR_VAL;
1214 } else {
1215
1216 *msg->err = ERR_OK;
1217 *msg->addr = *ipaddr;
1218 }
1219
1220 sys_sem_signal(msg->sem);
1221 }
1222
1223
1224
1225
1226
1227
1228
1229 void
1230 do_gethostbyname(void *arg)
1231 {
1232 struct dns_api_msg *msg = (struct dns_api_msg*)arg;
1233
1234 *msg->err = dns_gethostbyname(msg->name, msg->addr, do_dns_found, msg);
1235 if (*msg->err != ERR_INPROGRESS) {
1236
1237
1238 sys_sem_signal(msg->sem);
1239 }
1240 }
1241 #endif
1242
1243 #endif