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 /*-----------------------------------------------------------------------------------*/

Generated on Tue Dec 12 08:52:07 2006 for UbixOS V2 by  doxygen 1.4.7