# sockets.c

Go to the documentation of this file.

    00001 /*
    00002  * Copyright (c) 2001, Swedish Institute of Computer Science.
    00003  * All rights reserved.
    00004  *
    00005  * Redistribution and use in source and binary forms, with or without
    00006  * modification, are permitted provided that the following conditions
    00007  * are met:
    00008  * 1. Redistributions of source code must retain the above copyright
    00009  *    notice, this list of conditions and the following disclaimer.
    00010  * 2. Redistributions in binary form must reproduce the above copyright
    00011  *    notice, this list of conditions and the following disclaimer in the
    00012  *    documentation and/or other materials provided with the distribution.
    00013  * 3. Neither the name of the Institute nor the names of its contributors
    00014  *    may be used to endorse or promote products derived from this software
    00015  *    without specific prior written permission.
    00016  *
    00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
    00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
    00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    00027  * SUCH DAMAGE.
    00028  *
    00029  * This file is part of the lwIP TCP/IP stack.
    00030  *
    00031  * Author: Adam Dunkels <adam@sics.se>
    00032  *
    00033  * $Id: sockets_8c-source.html 88 2016-01-12 00:11:29Z reddawg $
    00034  */
    00035
    00036 #include <ubixos/types.h>
    00037
    00038 #include "net/debug.h"
    00039 #include "net/api.h"
    00040
    00041 #include "net/sockets.h"
    00042
    00043 #define NUM_SOCKETS 10
    00044
    00045 struct lwip_socket {
    00046   struct netconn *conn;
    00047   struct netbuf *lastdata;
    00048   uInt16 lastoffset;
    00049 };
    00050
    00051 static struct lwip_socket sockets[NUM_SOCKETS];
    00052
    00053 /*-----------------------------------------------------------------------------------*/
    00054 static struct lwip_socket *
    00055 get_socket(int s)
    00056 {
    00057   struct lwip_socket *sock;
    00058
    00059   if(s > NUM_SOCKETS) {
    00060     /* errno = EBADF; */
    00061     return NULL;
    00062   }
    00063
    00064   sock = &sockets[s];
    00065
    00066   if(sock->conn == NULL) {
    00067     /* errno = EBADF; */
    00068     return NULL;
    00069   }
    00070   return sock;
    00071 }
    00072 /*-----------------------------------------------------------------------------------*/
    00073 static int
    00074 alloc_socket(struct netconn *newconn)
    00075 {
    00076   int i;
    00077
    00078   /* allocate a new socket identifier */
    00079   for(i = 0; i < NUM_SOCKETS; ++i) {
    00080     if(sockets[i].conn == NULL) {
    00081       sockets[i].conn = newconn;
    00082       sockets[i].lastdata = NULL;
    00083       sockets[i].lastoffset = 0;
    00084       return i;
    00085     }
    00086   }
    00087   return -1;
    00088 }
    00089 /*-----------------------------------------------------------------------------------*/
    00090 int
    00091 lwip_accept(int s, struct sockaddr *addr, int *addrlen)
    00092 {
    00093   struct lwip_socket *sock;
    00094   struct netconn *newconn;
    00095   struct ip_addr *naddr;
    00096   uInt16 port;
    00097   int newsock;
    00098
    00099   sock = get_socket(s);
    00100   if(sock == NULL) {
    00101     return -1;
    00102   }
    00103
    00104   newconn = netconn_accept(sock->conn);
    00105
    00106   /* get the IP address and port of the remote host */
    00107   netconn_peer(newconn, &naddr, &port);
    00108
    00109   ((struct sockaddr_in *)addr)->sin_addr.s_addr = naddr->addr;
    00110   ((struct sockaddr_in *)addr)->sin_port = port;
    00111
    00112   newsock = alloc_socket(newconn);
    00113   if(newsock == -1) {
    00114     netconn_delete(newconn);
    00115     /* errno = ENOBUFS; */
    00116   }
    00117   return newsock;
    00118 }
    00119 /*-----------------------------------------------------------------------------------*/
    00120 int
    00121 lwip_bind(int s, struct sockaddr *name, int namelen)
    00122 {
    00123   struct lwip_socket *sock;
    00124   struct ip_addr remote_addr;
    00125   uInt16 remote_port;
    00126   err_t err;
    00127
    00128   sock = get_socket(s);
    00129   if(sock == NULL) {
    00130     return -1;
    00131   }
    00132
    00133   remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
    00134   remote_port = ((struct sockaddr_in *)name)->sin_port;
    00135
    00136   err = netconn_bind(sock->conn, &remote_addr, ntohs(remote_port));
    00137
    00138   if(err != ERR_OK) {
    00139     /* errno = ... */
    00140     return -1;
    00141   }
    00142
    00143   return 0;
    00144 }
    00145 /*-----------------------------------------------------------------------------------*/
    00146 int
    00147 lwip_close(int s)
    00148 {
    00149   struct lwip_socket *sock;
    00150
    00151   DEBUGF(SOCKETS_DEBUG, ("close: socket %d\n", s));
    00152   sock = get_socket(s);
    00153   if(sock == NULL) {
    00154     return -1;
    00155   }
    00156
    00157
    00158   netconn_delete(sock->conn);
    00159   if(sock->lastdata != NULL) {
    00160     netbuf_delete(sock->lastdata);
    00161   }
    00162   sock->lastdata = NULL;
    00163   sock->lastoffset = 0;
    00164   sock->conn = NULL;
    00165   return 0;
    00166 }
    00167 /*-----------------------------------------------------------------------------------*/
    00168 int
    00169 lwip_connect(int s, struct sockaddr *name, int namelen)
    00170 {
    00171   struct lwip_socket *sock;
    00172   struct ip_addr remote_addr;
    00173   uInt16 remote_port;
    00174   err_t err;
    00175
    00176   sock = get_socket(s);
    00177   if(sock == NULL) {
    00178     return -1;
    00179   }
    00180
    00181   remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
    00182   remote_port = ((struct sockaddr_in *)name)->sin_port;
    00183
    00184   err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
    00185
    00186   if(err != ERR_OK) {
    00187     /* errno = ... */
    00188     return -1;
    00189   }
    00190
    00191   return 0;
    00192 }
    00193 /*-----------------------------------------------------------------------------------*/
    00194 int
    00195 lwip_listen(int s, int backlog)
    00196 {
    00197   struct lwip_socket *sock;
    00198   err_t err;
    00199
    00200   sock = get_socket(s);
    00201   if(sock == NULL) {
    00202     return -1;
    00203   }
    00204
    00205   err = netconn_listen(sock->conn);
    00206
    00207   if(err != ERR_OK) {
    00208     /* errno = ... */
    00209     return -1;
    00210   }
    00211
    00212   return 0;
    00213 }
    00214 /*-----------------------------------------------------------------------------------*/
    00215 int
    00216 lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
    00217               struct sockaddr *from, int *fromlen)
    00218 {
    00219   struct lwip_socket *sock;
    00220   struct netbuf *buf;
    00221   uInt16 buflen, copylen;
    00222   struct ip_addr *addr;
    00223   uInt16 port;
    00224
    00225
    00226   sock = get_socket(s);
    00227   if(sock == NULL) {
    00228     return -1;
    00229   }
    00230
    00231   /* Check if there is data left from the last recv operation. */
    00232   if(sock->lastdata != NULL) {
    00233     buf = sock->lastdata;
    00234   } else {
    00235     /* No data was left from the previous operation, so we try to get
    00236        some from the network. */
    00237     buf = netconn_recv(sock->conn);
    00238
    00239     if(buf == NULL) {
    00240       /* We should really do some error checking here. */
    00241       return 0;
    00242     }
    00243   }
    00244
    00245   buflen = netbuf_len(buf);
    00246
    00247   buflen -= sock->lastoffset;
    00248
    00249   if(len > buflen) {
    00250     copylen = buflen;
    00251   } else {
    00252     copylen = len;
    00253   }
    00254
    00255   /* copy the contents of the received buffer into
    00256      the supplied memory pointer mem */
    00257   netbuf_copy_partial(buf, mem, copylen, sock->lastoffset);
    00258
    00259   /* If this is a TCP socket, check if there is data left in the
    00260      buffer. If so, it should be saved in the sock structure for next
    00261      time around. */
    00262   if(netconn_type(sock->conn) == NETCONN_TCP && buflen - copylen > 0) {
    00263     sock->lastdata = buf;
    00264     sock->lastoffset = buflen - copylen;
    00265   } else {
    00266     sock->lastdata = NULL;
    00267     sock->lastoffset = 0;
    00268     netbuf_delete(buf);
    00269   }
    00270
    00271   /* Check to see from where the data was. */
    00272   if(from != NULL && fromlen != NULL) {
    00273     addr = netbuf_fromaddr(buf);
    00274     port = htons(netbuf_fromport(buf));
    00275     ((struct sockaddr_in *)from)->sin_addr.s_addr = addr->addr;
    00276     ((struct sockaddr_in *)from)->sin_port = port;
    00277     *fromlen = sizeof(struct sockaddr_in);
    00278   }
    00279
    00280
    00281   /* if the length of the received data is larger than
    00282      len, this data is discarded and we return len.
    00283      otherwise we return the actual length of the received
    00284      data */
    00285   if(len > copylen) {
    00286     return copylen;
    00287   } else {
    00288     return len;
    00289   }
    00290 }
    00291 /*-----------------------------------------------------------------------------------*/
    00292 int
    00293 lwip_read(int s, void *mem, int len)
    00294 {
    00295   return lwip_recv(s, mem, len, 0);
    00296 }
    00297 /*-----------------------------------------------------------------------------------*/
    00298 int
    00299 lwip_recv(int s, void *mem, int len, unsigned int flags)
    00300 {
    00301   return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
    00302 }
    00303 /*-----------------------------------------------------------------------------------*/
    00304 int
    00305 lwip_send(int s, void *data, int size, unsigned int flags)
    00306 {
    00307   struct lwip_socket *sock;
    00308   struct netbuf *buf;
    00309   err_t err;
    00310
    00311   DEBUGF(SOCKETS_DEBUG, ("send: socket %d, size %d\n", s, size));
    00312
    00313   sock = get_socket(s);
    00314   if(sock == NULL) {
    00315     return -1;
    00316   }
    00317
    00318   switch(netconn_type(sock->conn)) {
    00319   case NETCONN_UDP:
    00320     /* create a buffer */
    00321     buf = netbuf_new();
    00322
    00323     if(buf == NULL) {
    00324       /* errno = ENOBUFS; */
    00325       return -1;
    00326     }
    00327
    00328     /* make the buffer point to the data that should
    00329        be sent */
    00330     netbuf_ref(buf, data, size);
    00331
    00332     /* send the data */
    00333     err = netconn_send(sock->conn, buf);
    00334
    00335     /* deallocated the buffer */
    00336     netbuf_delete(buf);
    00337     break;
    00338   case NETCONN_TCP:
    00339     err = netconn_write(sock->conn, data, size, NETCONN_COPY);
    00340     break;
    00341   default:
    00342     err = ERR_ARG;
    00343     break;
    00344   }
    00345   if(err != ERR_OK) {
    00346     /* errno = ... */
    00347     return -1;
    00348   }
    00349
    00350   return size;
    00351 }
    00352 /*-----------------------------------------------------------------------------------*/
    00353 int
    00354 lwip_sendto(int s, void *data, int size, unsigned int flags,
    00355        struct sockaddr *to, int tolen)
    00356 {
    00357   struct lwip_socket *sock;
    00358   struct ip_addr remote_addr, *addr;
    00359   uInt16 remote_port, port;
    00360   int ret;
    00361
    00362   sock = get_socket(s);
    00363   if(sock == NULL) {
    00364     return -1;
    00365   }
    00366
    00367   /* get the peer if currently connected */
    00368   netconn_peer(sock->conn, &addr, &port);
    00369
    00370   remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
    00371   remote_port = ((struct sockaddr_in *)to)->sin_port;
    00372   netconn_connect(sock->conn, &remote_addr, remote_port);
    00373
    00374   ret = lwip_send(s, data, size, flags);
    00375
    00376   /* reset the remote address and port number
    00377      of the connection */
    00378   netconn_connect(sock->conn, addr, port);
    00379   return ret;
    00380 }
    00381 /*-----------------------------------------------------------------------------------*/
    00382 int
    00383 lwip_socket(int domain, int type, int protocol)
    00384 {
    00385   struct netconn *conn;
    00386   int i;
    00387
    00388   /* create a netconn */
    00389   switch(type) {
    00390   case SOCK_DGRAM:
    00391     conn = netconn_new(NETCONN_UDP);
    00392     break;
    00393   case SOCK_STREAM:
    00394     conn = netconn_new(NETCONN_TCP);
    00395     break;
    00396   default:
    00397     /* errno = ... */
    00398     return -1;
    00399   }
    00400
    00401   if(conn == NULL) {
    00402     DEBUGF(SOCKETS_DEBUG, ("socket: could not create netconn.\n"));
    00403     /* errno = ENOBUFS; */
    00404     return -1;
    00405   }
    00406
    00407   i = alloc_socket(conn);
    00408
    00409   if(i == -1) {
    00410     /* errno = ENOBUFS; */
    00411     netconn_delete(conn);
    00412   }
    00413   return i;
    00414 }
    00415 /*-----------------------------------------------------------------------------------*/
    00416 int
    00417 lwip_write(int s, void *data, int size)
    00418 {
    00419   struct lwip_socket *sock;
    00420   err_t err;
    00421
    00422   DEBUGF(SOCKETS_DEBUG, ("write: socket %d, size %d\n", s, size));
    00423
    00424   sock = get_socket(s);
    00425   if(sock == NULL) {
    00426     return -1;
    00427   }
    00428
    00429   switch(netconn_type(sock->conn)) {
    00430   case NETCONN_UDP:
    00431     return lwip_send(s, data, size, 0);
    00432
    00433   case NETCONN_TCP:
    00434     err = netconn_write(sock->conn, data, size, NETCONN_COPY);
    00435     break;
    00436   default:
    00437     err = ERR_ARG;
    00438     break;
    00439   }
    00440   if(err != ERR_OK) {
    00441     /* errno = ... */
    00442     return -1;
    00443   }
    00444   return size;
    00445 }
    00446 /*-----------------------------------------------------------------------------------*/