Subversion Repositories HelenOS

Rev

Rev 4589 | Rev 4704 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2009 Lukas Mejdrech
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup socket
  30.  *  @{
  31.  */
  32.  
  33. /** @file
  34.  */
  35.  
  36. #include "../err.h"
  37.  
  38. #include "../include/in.h"
  39. #include "../include/inet.h"
  40.  
  41. #include "../include/socket.h"
  42. #include "../include/socket_errno.h"
  43.  
  44. #include "../structures/dynamic_fifo.h"
  45. #include "../structures/int_map.h"
  46. #include "../structures/packet/packet.h"
  47. #include "../structures/packet/packet_client.h"
  48.  
  49. #include "socket_core.h"
  50.  
  51. INT_MAP_IMPLEMENT( socket_cores, socket_core_t );
  52.  
  53. INT_MAP_IMPLEMENT( socket_ports, socket_core_ref );
  54.  
  55. int socket_bind( socket_cores_ref local_sockets, socket_ports_ref global_sockets, int socket_id, void * addr, size_t addrlen ){
  56.     ERROR_DECLARE;
  57.  
  58.     socket_core_ref         socket;
  59.     socket_core_ref *       socket_pointer;
  60.     struct sockaddr *       address;
  61.     struct sockaddr_in *    address_in;
  62.  
  63.     if( addrlen < sizeof( struct sockaddr )) return EINVAL;
  64.     address = ( struct sockaddr * ) addr;
  65.     switch( address->sa_family ){
  66.         case AF_INET:
  67.             if( addrlen != sizeof( struct sockaddr_in )) return EINVAL;
  68.             address_in = ( struct sockaddr_in * ) addr;
  69.             // find the socket
  70.             socket = socket_cores_find( local_sockets, socket_id );
  71.             if( ! socket ) return ENOTSOCK;
  72.             // try to find the port
  73.             socket_pointer = socket_ports_find( global_sockets, address_in->sin_port );
  74.             if( socket_pointer ){
  75.                 // already used
  76.                 return EADDRINUSE;
  77.             }
  78.             // disbind if bound
  79.             socket_ports_exclude( global_sockets, socket->port );
  80.             // create a wrapper
  81.             socket_pointer = ( socket_core_ref * ) malloc( sizeof( * socket_pointer ));
  82.             if( ! socket_pointer ) return ENOMEM;
  83.             * socket_pointer = socket;
  84.             // register the port
  85.             ERROR_CODE = socket_ports_add( global_sockets, address_in->sin_port, socket_pointer );
  86.             if( ERROR_CODE < 0 ){
  87.                 free( socket_pointer );
  88.             }
  89.             socket->port = address_in->sin_port;
  90.             break;
  91.         // TODO IPv6
  92.         default:
  93.             return EAFNOSUPPORT;
  94.     }
  95.     return EOK;
  96. }
  97.  
  98. int socket_create( socket_cores_ref local_sockets, int app_phone, int * socket_id ){
  99.     ERROR_DECLARE;
  100.  
  101.     socket_core_ref socket;
  102.     int             res;
  103.  
  104.     if( ! socket_id ) return EBADMEM;
  105.     socket = ( socket_core_ref ) malloc( sizeof( * socket ));
  106.     if( ! socket ) return ENOMEM;
  107.     // initialize
  108.     socket->phone = app_phone;
  109.     socket->port = -1;
  110.     socket->device_id = -1;
  111.     socket->peer_addr = NULL;
  112.     if( ERROR_OCCURRED( dyn_fifo_initialize( & socket->received, SOCKET_INITIAL_RECEIVED_SIZE ))){
  113.         free( socket );
  114.         return ERROR_CODE;
  115.     }
  116.     if( ERROR_OCCURRED( dyn_fifo_initialize( & socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE ))){
  117.         dyn_fifo_destroy( & socket->received );
  118.         free( socket );
  119.         return ERROR_CODE;
  120.     }
  121.     // get a next free socket number
  122.     socket->socket_id = socket_cores_count( local_sockets ) + 1;
  123.     // store the socket
  124.     res = socket_cores_add( local_sockets, socket->socket_id, socket );
  125.     if( res < 0 ){
  126.         dyn_fifo_destroy( & socket->received );
  127.         dyn_fifo_destroy( & socket->accepted );
  128.         free( socket );
  129.         return res;
  130.     }
  131.     // return the socket identifier
  132.     * socket_id = socket->socket_id;
  133.     return EOK;
  134. }
  135.  
  136. int socket_destroy( int packet_phone, int socket_id, socket_cores_ref local_sockets, socket_ports_ref global_sockets ){
  137.     socket_core_ref socket;
  138.     int             accepted_id;
  139.     int             packet_id;
  140.  
  141.     // find the socket
  142.     socket = socket_cores_find( local_sockets, socket_id );
  143.     if( ! socket ) return ENOTSOCK;
  144.     socket_ports_exclude( global_sockets, socket->port );
  145.     // destroy all accepted sockets
  146.     while(( accepted_id = dyn_fifo_pop( & socket->accepted )) >= 0 ){
  147.         socket_destroy( packet_phone, accepted_id, local_sockets, global_sockets );
  148.     }
  149.     // release all received packets
  150.     while(( packet_id = dyn_fifo_pop( & socket->received )) >= 0 ){
  151.         pq_release( packet_phone, packet_id );
  152.     }
  153.     dyn_fifo_destroy( & socket->received );
  154.     dyn_fifo_destroy( & socket->accepted );
  155.     socket_cores_exclude( local_sockets, socket_id );
  156.     return EOK;
  157. }
  158.  
  159. /** @}
  160.  */
  161.