A new object oriented network api that can be used to replace the one provided by the EthernetInterface library.

Dependents:   NetRelais TCP_Client_Example TCP_Server_Example UDP_Server_Example ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers select.cpp Source File

select.cpp

00001 /**
00002  * Copyright (c) 2012, Roy van Dam <roy@vandam-innovations.com>
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 are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright notice, this
00009  *    list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright notice,
00011  *    this list of conditions and the following disclaimer in the documentation
00012  *    and/or other materials provided with the distribution.
00013  *
00014  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00015  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00016  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00017  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00018  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00019  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00020  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00021  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00022  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00023  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00024  */
00025  
00026 #include "select.hpp"
00027 using namespace network;
00028 
00029 Select::~Select()
00030 {
00031     // Clear fd sets
00032     FD_ZERO(&this->_read_set);
00033     FD_ZERO(&this->_write_set);
00034 }
00035  
00036 int
00037 Select::wait(int timeout)
00038 {
00039     int max_fd = 0;
00040     Select::SocketList::iterator entry;
00041     
00042     // Clear fd sets
00043     FD_ZERO(&this->_read_set);
00044     FD_ZERO(&this->_write_set);
00045     
00046     // Create set for writing
00047     entry = this->_write_list.begin();
00048     for (; entry != this->_write_list.end(); entry++) {
00049         int socket = (*entry)->getHandle();
00050         if (socket == -1) {
00051             continue;
00052         }
00053         
00054         FD_SET(socket, &this->_write_set);
00055         max_fd = (max_fd > socket)
00056             ? max_fd
00057             : socket;
00058     }
00059     
00060     // Create set for reading
00061     entry = this->_read_list.begin();
00062     for (; entry != this->_read_list.end(); entry++) {
00063         int socket = (*entry)->getHandle();
00064         if (socket == -1) {
00065             continue;
00066         }
00067         
00068         FD_SET(socket, &this->_read_set);
00069         max_fd = (max_fd > socket)
00070             ? max_fd
00071             : socket;
00072     }
00073     
00074     // Reset iterators
00075     this->_write_list_iterator = this->_write_list.begin();
00076     this->_read_list_iterator = this->_read_list.begin();
00077     
00078     // Select on the created sets, wait until timeout.
00079     if (timeout > 0) {
00080         struct timeval _timeout;
00081         _timeout.tv_sec = timeout / 1000;
00082         _timeout.tv_usec = (timeout - (_timeout.tv_sec * 1000)) * 1000;
00083         
00084         return lwip_select(max_fd + 1, &this->_read_set, &this->_write_set, NULL, &_timeout);
00085     } else {
00086         // Select on the created sets, wait forever.
00087         return lwip_select(max_fd + 1, &this->_read_set, &this->_write_set, NULL, NULL);
00088     }
00089 }
00090 
00091 void
00092 Select::clear()
00093 {
00094     this->_read_list.clear();
00095     this->_write_list.clear();
00096 }
00097 
00098 void
00099 Select::set(Socket *socket, enum Mode mode)
00100 {
00101     switch (mode) {
00102         case Select::Read:
00103             if (this->_inReadList(socket) != this->_read_list.end()) {
00104                 break;
00105             }
00106             
00107             this->_read_list.push_back(socket);
00108             break;
00109         
00110         case Select::Write:
00111             if (this->_inWriteList(socket) != this->_write_list.end()) {
00112                 break;
00113             }
00114             
00115             this->_write_list.push_back(socket);
00116             break;
00117            
00118         case Select::ReadWrite:
00119             this->set(socket, Select::Read);
00120             this->set(socket, Select::Write);
00121             break;
00122     }
00123 }
00124 
00125 void
00126 Select::unset(Socket *socket, enum Mode mode)
00127 {
00128     Select::SocketList::iterator entry;
00129 
00130     switch (mode) {
00131         case Select::Read:
00132             entry = this->_inReadList(socket);
00133             if (entry == this->_read_list.end()) {
00134                 break;
00135             }
00136             
00137             this->_read_list.erase(entry);
00138             break;
00139         
00140         case Select::Write:
00141             entry = this->_inWriteList(socket);
00142             if (entry == this->_write_list.end()) {
00143                 break;
00144             }
00145             
00146             this->_write_list.erase(entry);
00147             break;
00148            
00149         case Select::ReadWrite:
00150             this->unset(socket, Select::Read);
00151             this->unset(socket, Select::Write);
00152             break;
00153     }
00154 }
00155 
00156 Socket *
00157 Select::getWritable()
00158 {
00159     if (this->_write_list_iterator == this->_write_list.end()) {
00160         return NULL;
00161     }
00162     
00163     for (; this->_write_list_iterator != this->_write_list.end(); this->_write_list_iterator++) {
00164         int socket = (*this->_write_list_iterator)->getHandle();
00165         if (socket == -1) {
00166             continue;
00167         }
00168         
00169         if (FD_ISSET(socket, &this->_write_set)) {
00170             Select::SocketList::iterator result = this->_write_list_iterator;
00171             this->_write_list_iterator++;
00172             return (*result);
00173         }
00174     }
00175     
00176     return NULL;
00177 }
00178 
00179 Socket *
00180 Select::getReadable()
00181 {
00182     if (this->_read_list_iterator == this->_read_list.end()) {
00183         return NULL;
00184     }
00185     
00186     for (; this->_read_list_iterator != this->_read_list.end(); this->_read_list_iterator++) {
00187         int socket = (*this->_read_list_iterator)->getHandle();
00188         if (socket == -1) {
00189             continue;
00190         }
00191         
00192         if (FD_ISSET(socket, &this->_read_set)) {
00193             Select::SocketList::iterator result = this->_read_list_iterator;
00194             this->_read_list_iterator++;
00195             return (*result);
00196         }
00197     }
00198     
00199     return NULL;
00200 }
00201 
00202 Select::SocketList::iterator
00203 Select::_inWriteList(Socket *socket)
00204 {
00205     Select::SocketList::iterator entry = this->_write_list.begin();
00206     for (; entry != this->_write_list.end(); entry++) {
00207         if ((*entry) == socket) {
00208             return entry;
00209         }
00210     }
00211     
00212     return this->_write_list.end();
00213 }
00214 
00215 Select::SocketList::iterator
00216 Select::_inReadList(Socket *socket)
00217 {
00218     Select::SocketList::iterator entry = this->_read_list.begin();
00219     for (; entry != this->_read_list.end(); entry++) {
00220         if ((*entry) == socket) {
00221             return entry;
00222         }
00223     }
00224     
00225     return this->_read_list.end();
00226 }