fix for corrupted graphics when manipulating config files
[open-ps2-loader.git] / modules / network / SMSTCPIP / api_lib.c
blobed2cc7e17411b66eae161350d71393238a0ee6f7
1 /*
2 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25 * OF SUCH DAMAGE.
27 * This file is part of the lwIP TCP/IP stack.
29 * Author: Adam Dunkels <adam@sics.se>
33 /* This is the part of the API that is linked with
34 the application */
36 #include "lwip/opt.h"
37 #include "lwip/api.h"
38 #include "lwip/api_msg.h"
39 #include "lwip/memp.h"
41 #include <thsemap.h>
42 #include <sysclib.h>
44 #include "smsutils.h"
46 extern void tcpip_apimsg(struct api_msg *apimsg);
49 struct netbuf* netbuf_new ( void ) {
50 struct netbuf *buf = memp_malloc ( MEMP_NETBUF );
52 if ( buf ) {
53 buf -> p = NULL;
54 buf -> ptr = NULL;
55 } /* end if */
57 return buf;
59 } /* end netbuf_new */
61 void netbuf_delete ( struct netbuf* buf ) {
63 if ( buf ) {
64 if ( buf -> p != NULL ) {
65 pbuf_free ( buf -> p );
66 buf -> p = buf -> ptr = NULL;
67 } /* end if */
68 memp_free ( MEMP_NETBUF, buf );
69 } /* end if */
71 } /* end netbuf_delete */
73 void netbuf_ref ( struct netbuf* buf, void* dataptr, u16_t size ) {
75 if ( buf -> p ) pbuf_free ( buf -> p );
77 buf -> p = pbuf_alloc ( PBUF_TRANSPORT, 0, PBUF_REF );
78 buf -> p -> payload = dataptr;
79 buf -> p -> len = buf -> p -> tot_len = size;
80 buf -> ptr = buf -> p;
82 } /* end netbuf_ref */
84 void netbuf_copy_partial (
85 struct netbuf* buf, void* dataptr, u16_t len, u16_t offset
86 ) {
88 struct pbuf* p;
89 u16_t left = 0;
91 if ( !buf || !dataptr ) return;
93 for ( p = buf -> p; left < len && p; p = p -> next ) {
95 if ( offset && offset >= p -> len )
97 offset -= p -> len;
99 else {
101 int buf_copy_len = p -> len - offset;
102 int lDiff = len - left;
104 lDiff = buf_copy_len > lDiff ? lDiff : buf_copy_len;
106 mips_memcpy (
107 &( ( char* )dataptr )[ left ],
108 &( ( char* )p -> payload )[ offset ],
109 lDiff
111 left += lDiff;
113 if ( left >= len ) return;
115 offset = 0;
117 } /* end else */
119 } /* end for */
121 } /* end netbuf_copy_partial */
123 struct
124 netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
125 void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
127 struct netconn *conn;
128 struct api_msg *msg;
130 conn = memp_malloc(MEMP_NETCONN);
131 if (conn == NULL) {
132 return NULL;
135 conn->err = ERR_OK;
136 conn->type = t;
137 conn->pcb.tcp = NULL;
139 if ((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
140 memp_free(MEMP_NETCONN, conn);
141 return NULL;
143 conn->recvmbox = SYS_MBOX_NULL;
144 conn->acceptmbox = SYS_MBOX_NULL;
145 conn->sem = SYS_SEM_NULL;
146 conn->state = NETCONN_NONE;
147 conn->socket = 0;
148 conn->callback = callback;
149 conn->recv_avail = 0;
151 if((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
152 memp_free(MEMP_NETCONN, conn);
153 return NULL;
156 msg->type = API_MSG_NEWCONN;
157 msg->msg.msg.bc.port = proto; /* misusing the port field */
158 msg->msg.conn = conn;
159 api_msg_post(msg);
160 sys_mbox_fetch(conn->mbox, NULL);
161 memp_free(MEMP_API_MSG, msg);
163 if ( conn->err != ERR_OK ) {
164 memp_free(MEMP_NETCONN, conn);
165 return NULL;
168 return conn;
171 err_t
172 netconn_delete(struct netconn *conn)
174 struct api_msg *msg;
175 void *mem;
177 if (conn == NULL) {
178 return ERR_OK;
181 if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
182 return ERR_MEM;
185 msg->type = API_MSG_DELCONN;
186 msg->msg.conn = conn;
187 api_msg_post(msg);
188 sys_mbox_fetch(conn->mbox, NULL);
189 memp_free(MEMP_API_MSG, msg);
191 /* Drain the recvmbox. */
192 if (conn->recvmbox != SYS_MBOX_NULL) {
193 while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
194 if (conn->type == NETCONN_TCP) {
195 pbuf_free((struct pbuf *)mem);
196 } else {
197 netbuf_delete((struct netbuf *)mem);
200 sys_mbox_free(conn->recvmbox);
201 conn->recvmbox = SYS_MBOX_NULL;
204 /* Drain the acceptmbox. */
205 if (conn->acceptmbox != SYS_MBOX_NULL) {
206 while (sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
207 netconn_delete((struct netconn *)mem);
210 sys_mbox_free(conn->acceptmbox);
211 conn->acceptmbox = SYS_MBOX_NULL;
214 sys_mbox_free(conn->mbox);
215 conn->mbox = SYS_MBOX_NULL;
216 if (conn->sem != SYS_SEM_NULL) {
217 sys_sem_free(conn->sem);
219 /* conn->sem = SYS_SEM_NULL;*/
220 memp_free(MEMP_NETCONN, conn);
221 return ERR_OK;
224 err_t
225 netconn_peer(struct netconn *conn, struct ip_addr *addr,
226 u16_t *port)
228 switch (conn->type) {
229 case NETCONN_RAW:
230 /* return an error as connecting is only a helper for upper layers */
231 return ERR_CONN;
232 case NETCONN_UDPLITE:
233 case NETCONN_UDPNOCHKSUM:
234 case NETCONN_UDP:
235 if (conn->pcb.udp == NULL ||
236 ((conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0))
237 return ERR_CONN;
238 *addr = (conn->pcb.udp->remote_ip);
239 *port = conn->pcb.udp->remote_port;
240 break;
241 case NETCONN_TCP:
242 if (conn->pcb.tcp == NULL)
243 return ERR_CONN;
244 *addr = (conn->pcb.tcp->remote_ip);
245 *port = conn->pcb.tcp->remote_port;
246 break;
248 return (conn->err = ERR_OK);
251 err_t
252 netconn_addr(struct netconn *conn, struct ip_addr **addr,
253 u16_t *port)
255 switch (conn->type) {
256 case NETCONN_RAW:
257 *addr = &(conn->pcb.raw->local_ip);
258 *port = conn->pcb.raw->protocol;
259 break;
260 case NETCONN_UDPLITE:
261 case NETCONN_UDPNOCHKSUM:
262 case NETCONN_UDP:
263 *addr = &(conn->pcb.udp->local_ip);
264 *port = conn->pcb.udp->local_port;
265 break;
266 case NETCONN_TCP:
267 *addr = &(conn->pcb.tcp->local_ip);
268 *port = conn->pcb.tcp->local_port;
269 break;
271 return (conn->err = ERR_OK);
274 err_t
275 netconn_bind(struct netconn *conn, struct ip_addr *addr,
276 u16_t port)
278 struct api_msg *msg;
280 if (conn == NULL) {
281 return ERR_VAL;
284 if (conn->type != NETCONN_TCP &&
285 conn->recvmbox == SYS_MBOX_NULL) {
286 if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
287 return ERR_MEM;
291 if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
292 return (conn->err = ERR_MEM);
294 msg->type = API_MSG_BIND;
295 msg->msg.conn = conn;
296 msg->msg.msg.bc.ipaddr = addr;
297 msg->msg.msg.bc.port = port;
298 api_msg_post(msg);
299 sys_mbox_fetch(conn->mbox, NULL);
300 memp_free(MEMP_API_MSG, msg);
301 return conn->err;
305 err_t
306 netconn_connect(struct netconn *conn, struct ip_addr *addr,
307 u16_t port)
309 struct api_msg *msg;
311 if (conn == NULL) {
312 return ERR_VAL;
316 if (conn->recvmbox == SYS_MBOX_NULL) {
317 if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
318 return ERR_MEM;
322 if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
323 return ERR_MEM;
325 msg->type = API_MSG_CONNECT;
326 msg->msg.conn = conn;
327 msg->msg.msg.bc.ipaddr = addr;
328 msg->msg.msg.bc.port = port;
329 api_msg_post(msg);
330 sys_mbox_fetch(conn->mbox, NULL);
331 memp_free(MEMP_API_MSG, msg);
332 return conn->err;
335 err_t
336 netconn_disconnect(struct netconn *conn)
338 struct api_msg *msg;
340 if (conn == NULL) {
341 return ERR_VAL;
344 if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
345 return ERR_MEM;
347 msg->type = API_MSG_DISCONNECT;
348 msg->msg.conn = conn;
349 api_msg_post(msg);
350 sys_mbox_fetch(conn->mbox, NULL);
351 memp_free(MEMP_API_MSG, msg);
352 return conn->err;
356 err_t
357 netconn_listen(struct netconn *conn)
359 struct api_msg *msg;
361 if (conn == NULL) {
362 return ERR_VAL;
365 if (conn->acceptmbox == SYS_MBOX_NULL) {
366 conn->acceptmbox = sys_mbox_new();
367 if (conn->acceptmbox == SYS_MBOX_NULL) {
368 return ERR_MEM;
372 if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
373 return (conn->err = ERR_MEM);
375 msg->type = API_MSG_LISTEN;
376 msg->msg.conn = conn;
377 api_msg_post(msg);
378 sys_mbox_fetch(conn->mbox, NULL);
379 memp_free(MEMP_API_MSG, msg);
380 return conn->err;
383 struct netconn *
384 netconn_accept(struct netconn *conn)
386 struct netconn *newconn;
388 if (conn == NULL) {
389 return NULL;
392 sys_mbox_fetch(conn->acceptmbox, (void **)&newconn);
393 /* Register event with callback */
394 if (conn->callback)
395 (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0);
397 return newconn;
400 struct netbuf *
401 netconn_recv(struct netconn *conn)
403 struct api_msg *msg;
404 struct netbuf *buf;
405 struct pbuf *p;
406 u16_t len;
408 if (conn == NULL) {
409 return NULL;
412 if (conn->recvmbox == SYS_MBOX_NULL) {
413 conn->err = ERR_CONN;
414 return NULL;
417 if (conn->err != ERR_OK) {
418 return NULL;
421 if (conn->type == NETCONN_TCP) {
422 if (conn->pcb.tcp->state == LISTEN) {
423 conn->err = ERR_CONN;
424 return NULL;
428 buf = memp_malloc(MEMP_NETBUF);
430 if (buf == NULL) {
431 conn->err = ERR_MEM;
432 return NULL;
435 sys_mbox_fetch(conn->recvmbox, (void **)&p);
437 if (p != NULL)
439 len = p->tot_len;
440 conn->recv_avail -= len;
442 else
443 len = 0;
445 /* Register event with callback */
446 if (conn->callback)
447 (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, len);
449 /* If we are closed, we indicate that we no longer wish to receive
450 data by setting conn->recvmbox to SYS_MBOX_NULL. */
451 if (p == NULL) {
452 memp_free(MEMP_NETBUF, buf);
453 sys_mbox_free(conn->recvmbox);
454 conn->recvmbox = SYS_MBOX_NULL;
455 return NULL;
458 buf->p = p;
459 buf->ptr = p;
460 buf->fromport = 0;
461 buf->fromaddr = NULL;
463 /* Let the stack know that we have taken the data. */
464 if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
465 conn->err = ERR_MEM;
466 return buf;
468 msg->type = API_MSG_RECV;
469 msg->msg.conn = conn;
470 if (buf != NULL) {
471 msg->msg.msg.len = buf->p->tot_len;
472 } else {
473 msg->msg.msg.len = 1;
475 api_msg_post(msg);
477 sys_mbox_fetch(conn->mbox, NULL);
478 memp_free(MEMP_API_MSG, msg);
479 } else {
480 sys_mbox_fetch(conn->recvmbox, (void **)&buf);
481 conn->recv_avail -= buf->p->tot_len;
482 /* Register event with callback */
483 if (conn->callback)
484 (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
487 return buf;
490 err_t
491 netconn_send(struct netconn *conn, struct netbuf *buf)
493 struct api_msg *msg;
495 if (conn == NULL) {
496 return ERR_VAL;
499 if (conn->err != ERR_OK) {
500 return conn->err;
503 if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
504 return (conn->err = ERR_MEM);
506 msg->type = API_MSG_SEND;
507 msg->msg.conn = conn;
508 msg->msg.msg.p = buf->p;
509 api_msg_post(msg);
511 sys_mbox_fetch(conn->mbox, NULL);
512 memp_free(MEMP_API_MSG, msg);
513 return conn->err;
517 err_t
518 netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
520 struct api_msg *msg;
521 u16_t len;
523 if (conn == NULL) {
524 return ERR_VAL;
527 if (conn->err != ERR_OK) {
528 return conn->err;
531 if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
532 return (conn->err = ERR_MEM);
534 msg->type = API_MSG_WRITE;
535 msg->msg.conn = conn;
538 conn->state = NETCONN_WRITE;
539 while (conn->err == ERR_OK && size > 0) {
540 msg->msg.msg.w.dataptr = dataptr;
541 msg->msg.msg.w.copy = copy;
543 if (conn->type == NETCONN_TCP) {
544 if (tcp_sndbuf(conn->pcb.tcp) == 0) {
545 sys_sem_wait(conn->sem);
546 if (conn->err != ERR_OK) {
547 goto ret;
550 if (size > tcp_sndbuf(conn->pcb.tcp)) {
551 /* We cannot send more than one send buffer's worth of data at a
552 time. */
553 len = tcp_sndbuf(conn->pcb.tcp);
554 } else {
555 len = size;
557 } else {
558 len = size;
561 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
562 msg->msg.msg.w.len = len;
563 api_msg_post(msg);
564 sys_mbox_fetch(conn->mbox, NULL);
565 if (conn->err == ERR_OK) {
566 dataptr = (void *)((u8_t *)dataptr + len);
567 size -= len;
568 } else if (conn->err == ERR_MEM) {
569 conn->err = ERR_OK;
570 sys_sem_wait(conn->sem);
571 } else {
572 goto ret;
575 ret:
576 memp_free(MEMP_API_MSG, msg);
577 conn->state = NETCONN_NONE;
579 return conn->err;
582 err_t
583 netconn_close(struct netconn *conn)
585 struct api_msg *msg;
587 if (conn == NULL) {
588 return ERR_VAL;
590 if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
591 return (conn->err = ERR_MEM);
594 conn->state = NETCONN_CLOSE;
595 again:
596 msg->type = API_MSG_CLOSE;
597 msg->msg.conn = conn;
598 api_msg_post(msg);
599 sys_mbox_fetch(conn->mbox, NULL);
600 if (conn->err == ERR_MEM &&
601 conn->sem != SYS_SEM_NULL) {
602 sys_sem_wait(conn->sem);
603 goto again;
605 conn->state = NETCONN_NONE;
606 memp_free(MEMP_API_MSG, msg);
607 return conn->err;