diff --git a/ext/pico_bsd/LICENSE b/ext/pico_bsd/LICENSE deleted file mode 100644 index 22fbe5d..0000000 --- a/ext/pico_bsd/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ -GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {description} - Copyright (C) {year} {fullname} - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - {signature of Ty Coon}, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. \ No newline at end of file diff --git a/ext/pico_bsd/README.md b/ext/pico_bsd/README.md deleted file mode 100644 index 9b896c0..0000000 --- a/ext/pico_bsd/README.md +++ /dev/null @@ -1,4 +0,0 @@ -picotcp-bsd -=========== - -BSD POSIX-compliant socket support for PicoTCP running on any OS. diff --git a/ext/pico_bsd/pico_bsd_sockets.c b/ext/pico_bsd/pico_bsd_sockets.c deleted file mode 100644 index 62a9058..0000000 --- a/ext/pico_bsd/pico_bsd_sockets.c +++ /dev/null @@ -1,1585 +0,0 @@ -/********************************************************************* -PicoTCP. Copyright (c) 2013 TASS Belgium NV. Some rights reserved. -See LICENSE and COPYING for usage. -Do not redistribute without a written permission by the Copyright -holders. - -Author: Maxime Vincent, Daniele Lacamera -*********************************************************************/ - -#include "pico_defines.h" -#include "pico_config.h" /* for zalloc and free */ -#include "pico_bsd_sockets.h" -#include "pico_osal.h" -#ifdef PICO_SUPPORT_SNTP_CLIENT -#include "pico_sntp_client.h" -#endif - -#include /* should be there in C99 */ - -#define SOCK_OPEN 0 -#define SOCK_BOUND 1 -#define SOCK_LISTEN 2 -#define SOCK_CONNECTED 3 -#define SOCK_ERROR 4 -#define SOCK_RESET_BY_PEER 5 -#define SOCK_CLOSED 100 - -#define bsd_dbg(...) do {} while(0) -#define bsd_dbg_select(...) do {} while(0) - -/* Global signal sent on any event (for select) */ -void * picoLock = NULL; /* pico stack lock */ -void * pico_signal_select = NULL; /* pico global signal for select */ -void * pico_signal_tick = NULL; /* pico tick signal, e.g. coming from a driver ISR */ - -struct pico_bsd_endpoint { - struct pico_socket *s; - int socket_fd; - int posix_fd; /* TODO: ifdef... */ - uint8_t in_use; - uint8_t state; /* for pico_state */ - uint8_t nonblocking; /* The non-blocking flag, for non-blocking socket operations */ - uint16_t events; /* events that we filter for */ - uint16_t revents; /* received events */ - uint16_t proto; - void * mutex_lock; /* mutex for clearing revents */ - void * signal; /* signals new events */ - uint32_t timeout; /* this is used for timeout sockets */ - int error; /* used for SO_ERROR sockopt after connect() */ -}; - -/* MACRO's */ -#define VALIDATE_NULL(param) \ - if(!param) \ - { \ - return -1; \ - } - -#define VALIDATE_ONE(param,value) \ - if(param != value) { \ - pico_err = PICO_ERR_EINVAL; \ - errno = pico_err; \ - return -1; \ - } - -#define VALIDATE_TWO(param,value1,value2) \ - if(param != value1 && param != value2) { \ - pico_err = PICO_ERR_EINVAL; \ - errno = pico_err; \ - return -1; \ - } - - -/* Private function prototypes */ -static void pico_event_clear(struct pico_bsd_endpoint *ep, uint16_t events); -static uint16_t pico_bsd_wait(struct pico_bsd_endpoint * ep, int read, int write, int close); -static void pico_socket_event(uint16_t ev, struct pico_socket *s); - - -/************************/ -/* Public API functions */ -/************************/ -void pico_bsd_init(void) -{ - pico_signal_select = pico_signal_init(); - pico_signal_tick = pico_signal_init(); - picoLock = pico_mutex_init(); -} - -void pico_bsd_deinit(void) -{ - pico_mutex_deinit(picoLock); -} - -/* just ticks the stack twice */ -void pico_bsd_stack_tick(void) -{ - pico_mutex_lock(picoLock); - pico_stack_tick(); - pico_stack_tick(); - pico_mutex_unlock(picoLock); -} - -/* ticks the stack, but wait for a signal with a timeout (e.g. from the driver interrupt) */ -void pico_bsd_stack_tick_timeout(int timeout_ms) -{ - pico_signal_wait_timeout(pico_signal_tick, timeout_ms); - pico_bsd_stack_tick(); -} - -/** Declarations of helper functions **/ -static struct pico_bsd_endpoint *pico_bsd_create_socket(void); -static int get_free_sd(struct pico_bsd_endpoint *ep); -static int new_sd(struct pico_bsd_endpoint *ep); -static void free_up_ep(struct pico_bsd_endpoint *ep); -static struct pico_bsd_endpoint *get_endpoint(int sd, int set_err); -static int bsd_to_pico_addr(union pico_address *addr, struct sockaddr *_saddr, socklen_t socklen); -static uint16_t bsd_to_pico_port(struct sockaddr *_saddr, socklen_t socklen); -static int pico_addr_to_bsd(struct sockaddr *_saddr, socklen_t socklen, union pico_address *addr, uint16_t net); -static int pico_port_to_bsd(struct sockaddr *_saddr, socklen_t socklen, uint16_t port); - -/** Global Sockets descriptors array **/ -static struct pico_bsd_endpoint **PicoSockets = NULL; -static int PicoSocket_max = 0; - -/*** Public socket functions ***/ - -/* Socket interface. */ -int pico_newsocket(int domain, int type, int proto) -{ - struct pico_bsd_endpoint * ep = NULL; - (void)proto; - -#ifdef PICO_SUPPORT_IPV6 - VALIDATE_TWO(domain,AF_INET, AF_INET6); -#else - VALIDATE_ONE(domain, AF_INET); -#endif - VALIDATE_TWO(type,SOCK_STREAM,SOCK_DGRAM); - - if (AF_INET6 != PICO_PROTO_IPV6) { - if (domain == AF_INET6) - domain = PICO_PROTO_IPV6; - else - domain = PICO_PROTO_IPV4; - } - - if (SOCK_STREAM != PICO_PROTO_TCP) { - if (type == SOCK_STREAM) - type = PICO_PROTO_TCP; - else - type = PICO_PROTO_UDP; - } - - pico_mutex_lock(picoLock); - ep = pico_bsd_create_socket(); - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - - ep->proto = type; - - ep->s = pico_socket_open(domain, type,&pico_socket_event); - if (!ep->s) - { - PICO_FREE(ep); - pico_mutex_unlock(picoLock); - return -1; - } - - ep->s->priv = ep; /* let priv point to the endpoint struct */ - - /* open picotcp endpoint */ - ep->state = SOCK_OPEN; - ep->mutex_lock = pico_mutex_init(); - ep->signal = pico_signal_init(); - ep->error = pico_err; - pico_mutex_unlock(picoLock); - return ep->socket_fd; -} - - -int pico_bind(int sd, struct sockaddr * local_addr, socklen_t socklen) -{ - union pico_address addr = { .ip4 = { 0 } }; - uint16_t port; - struct pico_bsd_endpoint *ep = get_endpoint(sd, 1); - - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - VALIDATE_NULL(local_addr); - VALIDATE_TWO(socklen, SOCKSIZE, SOCKSIZE6); - - if (bsd_to_pico_addr(&addr, local_addr, socklen) < 0) - { - ep->error = PICO_ERR_EINVAL; - errno = pico_err; - return -1; - } - port = bsd_to_pico_port(local_addr, socklen); - - pico_mutex_lock(picoLock); - if(pico_socket_bind(ep->s, &addr, &port) < 0) - { - ep->error = pico_err; - errno = pico_err; - pico_mutex_unlock(picoLock); - return -1; - } - - ep->state = SOCK_BOUND; - pico_mutex_unlock(picoLock); - - return 0; -} - -int pico_getsockname(int sd, struct sockaddr * local_addr, socklen_t *socklen) -{ - union pico_address addr; - uint16_t port, proto; - struct pico_bsd_endpoint *ep = get_endpoint(sd, 1); - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - VALIDATE_NULL(local_addr); - VALIDATE_NULL(socklen); - pico_mutex_lock(picoLock); - if(pico_socket_getname(ep->s, &addr, &port, &proto) < 0) - { - ep->error = pico_err; - errno = pico_err; - pico_mutex_unlock(picoLock); - return -1; - } - - if (proto == PICO_PROTO_IPV6) - *socklen = SOCKSIZE6; - else - *socklen = SOCKSIZE; - - if (pico_addr_to_bsd(local_addr, *socklen, &addr, proto) < 0) { - ep->error = pico_err; - errno = pico_err; - pico_mutex_unlock(picoLock); - return -1; - } - pico_mutex_unlock(picoLock); - pico_port_to_bsd(local_addr, *socklen, port); - ep->error = pico_err; - return 0; -} - -int pico_getpeername(int sd, struct sockaddr * remote_addr, socklen_t *socklen) -{ - union pico_address addr; - uint16_t port, proto; - struct pico_bsd_endpoint *ep = get_endpoint(sd, 1); - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - VALIDATE_NULL(remote_addr); - VALIDATE_NULL(socklen); - pico_mutex_lock(picoLock); - if(pico_socket_getpeername(ep->s, &addr, &port, &proto) < 0) - { - pico_mutex_unlock(picoLock); - return -1; - } - - if (proto == PICO_PROTO_IPV6) - *socklen = SOCKSIZE6; - else - *socklen = SOCKSIZE; - - if (pico_addr_to_bsd(remote_addr, *socklen, &addr, proto) < 0) { - pico_mutex_unlock(picoLock); - return -1; - } - pico_mutex_unlock(picoLock); - pico_port_to_bsd(remote_addr, *socklen, port); - return 0; -} - - -int pico_listen(int sd, int backlog) -{ - struct pico_bsd_endpoint *ep = get_endpoint(sd, 1); - - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - VALIDATE_NULL(ep->s); - VALIDATE_ONE(ep->state, SOCK_BOUND); - - pico_mutex_lock(picoLock); - - if(pico_socket_listen(ep->s, backlog) < 0) - { - ep->error = pico_err; - errno = pico_err; - pico_mutex_unlock(picoLock); - return -1; - } - ep->state = SOCK_LISTEN; - - ep->error = pico_err; - pico_mutex_unlock(picoLock); - return 0; -} - -int pico_connect(int sd, struct sockaddr *_saddr, socklen_t socklen) -{ - struct pico_bsd_endpoint *ep = get_endpoint(sd, 1); - union pico_address addr; - uint16_t port; - uint16_t ev = 0; - int ret; - - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - VALIDATE_NULL(_saddr); - if (bsd_to_pico_addr(&addr, _saddr, socklen) < 0) - { - ep->error = PICO_ERR_EINVAL; - errno = pico_err; - return -1; - } - port = bsd_to_pico_port(_saddr, socklen); - pico_mutex_lock(picoLock); - ret = pico_socket_connect(ep->s, &addr, port); - pico_mutex_unlock(picoLock); - if (ret < 0) { - ep->error = pico_err; - return -1; - } - - if (ep->nonblocking) { - pico_err = PICO_ERR_EAGAIN; - ep->error = pico_err; - } else { - /* wait for event */ - ev = pico_bsd_wait(ep, 0, 0, 0); /* wait for ERR, FIN and CONN */ - } - - if(ev & PICO_SOCK_EV_CONN) - { - /* clear the EV_CONN event */ - pico_event_clear(ep, PICO_SOCK_EV_CONN); - ep->error = pico_err; - return 0; - } else { - if (!(ep->nonblocking)) - pico_socket_close(ep->s); - } - ep->error = pico_err; - errno = pico_err; - return -1; -} - -int pico_isconnected(int sd) { - struct pico_bsd_endpoint *ep = NULL; - int state = 0; - - ep = get_endpoint(sd, 1); - - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - - pico_mutex_lock(picoLock); - if(ep->state == SOCK_CONNECTED) { - state = 1; - } - pico_mutex_unlock(picoLock); - - return state; -} - -int pico_accept(int sd, struct sockaddr *_orig, socklen_t *socklen) -{ - struct pico_bsd_endpoint *ep, * client_ep = NULL; - uint16_t events; - union pico_address picoaddr; - uint16_t port; - - ep = get_endpoint(sd, 1); - - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - VALIDATE_ONE(ep->state, SOCK_LISTEN); - - if (ep->nonblocking) - events = PICO_SOCK_EV_CONN; - else - events = pico_bsd_wait(ep, 0, 0, 0); /* Wait for CONN, FIN and ERR */ - - if(events & PICO_SOCK_EV_CONN) - { - struct pico_socket *s; - pico_mutex_lock(picoLock); - s = pico_socket_accept(ep->s,&picoaddr,&port); - if (!s) - { - ep->error = pico_err; - errno = pico_err; - pico_mutex_unlock(picoLock); - return -1; - } - - /* Create a new client EP, only after the accept returned succesfully */ - client_ep = pico_bsd_create_socket(); - if (!client_ep) - { - ep->error = pico_err; - errno = pico_err; - pico_mutex_unlock(picoLock); - return -1; - } - client_ep->s = s; - client_ep->state = SOCK_OPEN; - client_ep->mutex_lock = pico_mutex_init(); - client_ep->signal = pico_signal_init(); - - client_ep->s->priv = client_ep; - pico_event_clear(ep, PICO_SOCK_EV_CONN); /* clear the CONN event the listening socket */ - if (client_ep->s->net->proto_number == PICO_PROTO_IPV4) - *socklen = SOCKSIZE; - else - *socklen = SOCKSIZE6; - client_ep->state = SOCK_CONNECTED; - if (pico_addr_to_bsd(_orig, *socklen, &picoaddr, client_ep->s->net->proto_number) < 0) { - client_ep->in_use = 0; - pico_mutex_unlock(picoLock); - return -1; - } - pico_port_to_bsd(_orig, *socklen, port); - - client_ep->in_use = 1; - pico_mutex_unlock(picoLock); - ep->error = pico_err; - return client_ep->socket_fd; - } - client_ep->in_use = 0; - ep->error = pico_err; - errno = pico_err; - return -1; -} - -int pico_sendto(int sd, void * buf, int len, int flags, struct sockaddr *_dst, socklen_t socklen) -{ - int retval = 0; - int tot_len = 0; - uint16_t port; - union pico_address picoaddr; - struct pico_bsd_endpoint *ep = get_endpoint(sd, 1); - - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - - if (!buf || (len <= 0)) { - pico_err = PICO_ERR_EINVAL; - errno = pico_err; - ep->error = pico_err; - return -1; - } - - while (tot_len < len) { - /* Write to the pico socket */ - pico_mutex_lock(picoLock); - if (_dst == NULL) { - retval = pico_socket_send(ep->s, ((uint8_t *)buf) + tot_len, len - tot_len); - } else { - if (bsd_to_pico_addr(&picoaddr, _dst, socklen) < 0) { - ep->error = PICO_ERR_EINVAL; - errno = pico_err; - pico_mutex_unlock(picoLock); - return -1; - } - port = bsd_to_pico_port(_dst, socklen); - retval = pico_socket_sendto(ep->s, ((uint8_t *)buf) + tot_len, len - tot_len, &picoaddr, port); - } - pico_event_clear(ep, PICO_SOCK_EV_WR); - pico_mutex_unlock(picoLock); - - /* If sending failed, return an error */ - if (retval < 0) - { - ep->error = pico_err; - errno = pico_err; - pico_event_clear(ep, PICO_SOCK_EV_WR); - return -1; - } - - if (retval > 0) - { - tot_len += retval; - break; - } - - if (ep->nonblocking) - break; - - /* If sent bytes (retval) < len-tot_len: socket full, we need to wait for a new WR event */ - if (retval < (len - tot_len)) - { - uint16_t ev = 0; - /* wait for a new WR or CLOSE event */ - ev = pico_bsd_wait(ep, 0, 1, 1); - - if (ev & (PICO_SOCK_EV_ERR | PICO_SOCK_EV_FIN | PICO_SOCK_EV_CLOSE)) - { - ep->error = pico_err; - errno = pico_err; - pico_event_clear(ep, PICO_SOCK_EV_WR); - /* closing and freeing the socket is done in the event handler */ - return -1; - } - } - tot_len += retval; - } - ep->error = pico_err; - return tot_len; -} - -int pico_fcntl(int sd, int cmd, int arg) -{ - struct pico_bsd_endpoint *ep = get_endpoint(sd, 1); - if (!ep) { - pico_err = PICO_ERR_EINVAL; - errno = pico_err; - return -1; - } - - if (cmd == F_SETFL) { - if ((arg & O_NONBLOCK) != 0) { - ep->nonblocking = 1; - } else { - ep->nonblocking = 0; - } - ep->error = PICO_ERR_NOERR; - return 0; - } - - if (cmd == F_GETFL) { - (void)arg; /* F_GETFL: arg is ignored */ - ep->error = PICO_ERR_NOERR; - if (ep->nonblocking) - return O_NONBLOCK; - else - return 0; - } - - if (cmd == F_SETFD) { - (void)arg; - ep->error = PICO_ERR_NOERR; - return 0; - } - - - pico_err = PICO_ERR_EINVAL; - errno = pico_err; - ep->error = pico_err; - return -1; -} - -/* - * RETURN VALUE - * Upon successful completion, recv_from() shall return the length of the - * message in bytes. If no messages are available to be received and the - * peer has performed an orderly shutdown, recv() shall return 0. Otherwise, - * −1 shall be returned and errno set to indicate the error. - */ -int pico_recvfrom(int sd, void * _buf, int len, int flags, struct sockaddr *_addr, socklen_t *socklen) -{ - int retval = 0; - int tot_len = 0; - struct pico_bsd_endpoint *ep = get_endpoint(sd, 1); - union pico_address picoaddr; - uint16_t port; - unsigned char *buf = (unsigned char *)_buf; - bsd_dbg("Recvfrom called \n"); - - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - - if (ep->state == SOCK_RESET_BY_PEER) { - /* not much to do here. Peer has nothing to say. */ - return 0; - } - - if (!buf || (len <= 0)) { - pico_err = PICO_ERR_EINVAL; - errno = pico_err; - ep->error = pico_err; - return -1; - } - - while (tot_len < len) { - pico_mutex_lock(picoLock); - retval = pico_socket_recvfrom(ep->s, buf + tot_len , len - tot_len, &picoaddr, &port); - pico_mutex_unlock(picoLock); - bsd_dbg("pico_socket_recvfrom returns %d, first bytes are %c-%c-%c-%c\n", retval, buf[0], buf[1], buf[2], buf[3]); - - /* pico_socket_recvfrom failed */ - if (retval < 0) { - /* data was received */ - if (tot_len > 0) - { - bsd_dbg("Recvfrom returning %d\n", tot_len); - ep->error = pico_err; - return tot_len; - } - /* no data was received yet */ - ep->error = pico_err; - if (pico_err == PICO_ERR_ESHUTDOWN) /* If no messages are available to be received and the peer has performed an orderly shutdown, recvfrom() shall return 0. */ - { - return 0; - } - else /* Otherwise, the function shall return −1 and set errno to indicate the error. */ - { - return -1; - } - } - - /* If received 0 bytes, return -1 or amount of bytes received */ - if (retval == 0) { - pico_event_clear(ep, PICO_SOCK_EV_RD); - if (tot_len > 0) { - bsd_dbg("Recvfrom returning %d\n", tot_len); - ep->error = pico_err; - return tot_len; - } - } - - if (retval > 0) { - if (ep->proto == PICO_PROTO_UDP) { - if (_addr && socklen > 0) - { - if (pico_addr_to_bsd(_addr, *socklen, &picoaddr, ep->s->net->proto_number) < 0) { - pico_err = PICO_ERR_EINVAL; - errno = pico_err; - ep->error = pico_err; - return -1; - } - pico_port_to_bsd(_addr, *socklen, port); - } - /* If in a recvfrom call, for UDP we should return immediately after the first dgram */ - ep->error = pico_err; - return retval + tot_len; - } else { - /* TCP: continue until recvfrom = 0, socket buffer empty */ - tot_len += retval; - continue; - } - } - - if (ep->nonblocking) - { - if (retval == 0) - { - pico_err = PICO_ERR_EAGAIN; /* or EWOULDBLOCK */ - errno = pico_err; - retval = -1; /* BSD-speak: -1 == 0 bytes received */ - } - break; - } - - /* If recv bytes (retval) < len-tot_len: socket empty, we need to wait for a new RD event */ - if (retval < (len - tot_len)) - { - uint16_t ev = 0; - /* wait for a new RD event -- also wait for CLOSE event */ - ev = pico_bsd_wait(ep, 1, 0, 1); - if (ev & (PICO_SOCK_EV_ERR | PICO_SOCK_EV_FIN | PICO_SOCK_EV_CLOSE)) - { - /* closing and freeing the socket is done in the event handler */ - pico_event_clear(ep, PICO_SOCK_EV_RD); - ep->error = pico_err; - return 0; /* return 0 on a properly closed socket */ - } - } - tot_len += retval; - } - pico_event_clear(ep, PICO_SOCK_EV_RD); // What if still space available and we clear it here?? - bsd_dbg("Recvfrom returning %d (full block)\n", tot_len); - ep->error = pico_err; - - if (tot_len == 0) - { - errno = pico_err; - tot_len = -1; /* BSD-speak: -1 == 0 bytes received */ - } - return tot_len; -} - -int pico_write(int sd, void * buf, int len) -{ - return pico_sendto(sd, buf, len, 0, NULL, 0); -} - -int pico_send(int sd, void * buf, int len, int flags) -{ - return pico_sendto(sd, buf, len, flags, NULL, 0); -} - -int pico_read(int sd, void * buf, int len) -{ - return pico_recvfrom(sd, buf, len, 0, NULL, 0); -} - -int pico_recv(int sd, void * buf, int len, int flags) -{ - return pico_recvfrom(sd, buf, len, flags, NULL, 0); -} - - - -int pico_close(int sd) -{ - struct pico_bsd_endpoint *ep = get_endpoint(sd, 1); - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - - if (ep->s && ep->in_use) /* valid socket, try to close it */ - { - pico_mutex_lock(picoLock); - pico_socket_close(ep->s); - ep->s->priv = NULL; - pico_mutex_unlock(picoLock); - } - ep->in_use = 0; - ep->error = pico_err; - return 0; -} - -int pico_shutdown(int sd, int how) -{ - struct pico_bsd_endpoint *ep = get_endpoint(sd, 1); - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - - if(ep->s) /* valid socket, try to close it */ - { - pico_mutex_lock(picoLock); - pico_socket_shutdown(ep->s, how); - ep->error = pico_err; - pico_mutex_unlock(picoLock); - } else { - ep->error = PICO_ERR_EINVAL; - errno = pico_err; - } - return 0; -} - -int pico_join_multicast_group(int sd, const char *address, const char *local) { - - int ret; - struct pico_ip_mreq mreq={}; - - pico_string_to_ipv4(address, &mreq.mcast_group_addr.ip4.addr); - pico_string_to_ipv4(local, &mreq.mcast_link_addr.ip4.addr); - ret = pico_setsockopt(sd, SOL_SOCKET, PICO_IP_ADD_MEMBERSHIP, &mreq, sizeof(struct pico_ip_mreq)); - - return ret; -} - -/*** Helper functions ***/ -static int bsd_to_pico_addr(union pico_address *addr, struct sockaddr *_saddr, socklen_t socklen) -{ - VALIDATE_TWO(socklen, SOCKSIZE, SOCKSIZE6); - if (socklen == SOCKSIZE6) { - struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)_saddr; - memcpy(&addr->ip6.addr, &saddr->sin6_addr.s6_addr, 16); - saddr->sin6_family = AF_INET6; - } else { - struct sockaddr_in *saddr = (struct sockaddr_in *)_saddr; - addr->ip4.addr = saddr->sin_addr.s_addr; - saddr->sin_family = AF_INET; - } - return 0; -} - -static uint16_t bsd_to_pico_port(struct sockaddr *_saddr, socklen_t socklen) -{ - VALIDATE_TWO(socklen, SOCKSIZE, SOCKSIZE6); - if (socklen == SOCKSIZE6) { - struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)_saddr; - return saddr->sin6_port; - } else { - struct sockaddr_in *saddr = (struct sockaddr_in *)_saddr; - return saddr->sin_port; - } -} - -static int pico_port_to_bsd(struct sockaddr *_saddr, socklen_t socklen, uint16_t port) -{ - if (socklen == SOCKSIZE6) { - struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)_saddr; - saddr->sin6_port = port; - return 0; - } else { - struct sockaddr_in *saddr = (struct sockaddr_in *)_saddr; - saddr->sin_port = port; - return 0; - } - pico_err = PICO_ERR_EINVAL; - errno = pico_err; - return -1; -} - -static int pico_addr_to_bsd(struct sockaddr *_saddr, socklen_t socklen, union pico_address *addr, uint16_t net) -{ - VALIDATE_TWO(socklen, SOCKSIZE, SOCKSIZE6); - if ((socklen == SOCKSIZE6) && (net == PICO_PROTO_IPV6)) { - struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)_saddr; - memcpy(&saddr->sin6_addr.s6_addr, &addr->ip6.addr, 16); - saddr->sin6_family = AF_INET6; - } else if ((socklen == SOCKSIZE) && (net == PICO_PROTO_IPV4)) { - struct sockaddr_in *saddr = (struct sockaddr_in *)_saddr; - saddr->sin_addr.s_addr = addr->ip4.addr; - saddr->sin_family = AF_INET; - } - return 0; -} - -static void free_up_ep(struct pico_bsd_endpoint *ep) -{ - if (ep->signal) - pico_signal_deinit(ep->signal); - if (ep->mutex_lock) - pico_mutex_deinit(ep->mutex_lock); - PICO_FREE(ep); -} - -static int get_free_sd(struct pico_bsd_endpoint *ep) -{ - int i; - for (i = 0; i < PicoSocket_max; i++) { - if (!PicoSockets[i]->in_use) { - free_up_ep(PicoSockets[i]); - PicoSockets[i] = ep; - return i; - } - } - return -1; -} - -/* DLA TODO: make a GC for freeing up the last socket descriptor periodically if not in use */ - -static int new_sd(struct pico_bsd_endpoint *ep) -{ - int sd = PicoSocket_max; - struct pico_bsd_endpoint **new; - new = PICO_ZALLOC(sizeof(void *) * ++PicoSocket_max); - if (!new) { - PicoSocket_max--; - pico_err = PICO_ERR_ENOMEM; - errno = pico_err; - return -1; - } - if (sd > 0) { - memcpy(new, PicoSockets, sd * sizeof(void *)); - PICO_FREE(PicoSockets); - } - PicoSockets = new; - new[sd] = ep; - return sd; -} - -/* picoLock must be taken already ! */ -static struct pico_bsd_endpoint *pico_bsd_create_socket(void) -{ - struct pico_bsd_endpoint *ep = PICO_ZALLOC(sizeof(struct pico_bsd_endpoint)); - if (!ep) { - pico_err = PICO_ERR_ENOMEM; - errno = pico_err; - } - ep->in_use = 1; - ep->socket_fd = get_free_sd(ep); - if (ep->socket_fd < 0) { - ep->socket_fd = new_sd(ep); - } - return ep; -} - - -#ifndef PICO_EBADFD -# define PICO_EBADFD 77 /* File descriptor in bad state */ -#endif - -static struct pico_bsd_endpoint *get_endpoint(int sd, int set_err) -{ - if ((sd > PicoSocket_max) || (sd < 0) || - (PicoSockets[sd]->in_use == 0)) { - if (set_err) - { - pico_err = PICO_EBADFD; - errno = pico_err; - } - return NULL; - } - return PicoSockets[sd]; -} - -/* wait for one of the selected events, return any of those that occurred */ -uint16_t pico_bsd_select(struct pico_bsd_endpoint *ep) -{ - uint16_t events = ep->events & ep->revents; /* maybe an event we are waiting for, was already queued ? */ - /* wait for one of the selected events... */ - while (!events) - { - pico_signal_wait(ep->signal); - events = (ep->revents & ep->events); /* filter for the events we were waiting for */ - } - /* the event we were waiting for happened, now report it */ - return events; /* return any event(s) that occurred, that we were waiting for */ -} - - -/****************************/ -/* Private helper functions */ -/****************************/ -static uint16_t pico_bsd_wait(struct pico_bsd_endpoint * ep, int read, int write, int close) -{ - pico_mutex_lock(ep->mutex_lock); - - ep->events = PICO_SOCK_EV_ERR; - ep->events |= PICO_SOCK_EV_FIN; - ep->events |= PICO_SOCK_EV_CONN; - if (close) - ep->events |= PICO_SOCK_EV_CLOSE; - if (read) - ep->events |= PICO_SOCK_EV_RD; - if (write) - ep->events |= PICO_SOCK_EV_WR; - - pico_mutex_unlock(ep->mutex_lock); - - return pico_bsd_select(ep); -} - - -static void pico_event_clear(struct pico_bsd_endpoint *ep, uint16_t events) -{ - pico_mutex_lock(ep->mutex_lock); - ep->revents &= ~events; /* clear those events */ - pico_mutex_unlock(ep->mutex_lock); -} - -/* NOTE: __NO__ picoLock'ing here !! */ -/* this is called from pico_stack_tick, so picoLock is already locked */ -static void pico_socket_event(uint16_t ev, struct pico_socket *s) -{ - struct pico_bsd_endpoint * ep = (struct pico_bsd_endpoint *)(s->priv); - if (!s) - return; - if(!ep || !ep->s || !ep->mutex_lock || !ep->signal ) - { - /* DLA: do not call close upon SOCK_CLOSE, we might still write. */ - if(ev & (PICO_SOCK_EV_FIN | PICO_SOCK_EV_ERR) ) - { - pico_signal_send(pico_signal_select); /* Signal this event globally (e.g. for select()) */ - pico_socket_close(s); - } - - if (ev & PICO_SOCK_EV_CLOSE) - pico_signal_send(pico_signal_select); - - /* endpoint not initialized yet! */ - return; - } - - if(ep->in_use != 1) - return; - - pico_mutex_lock(ep->mutex_lock); /* lock over the complete body is needed, - as the event might get cleared in another process.. */ - ep->revents |= ev; /* set those events */ - - if(ev & PICO_SOCK_EV_CONN) - { - if(ep->state != SOCK_LISTEN) - { - ep->state = SOCK_CONNECTED; - } - } - - if(ev & PICO_SOCK_EV_ERR) - { - ep->state = SOCK_RESET_BY_PEER; - } - - if (ev & PICO_SOCK_EV_CLOSE) { - ep->state = SOCK_RESET_BY_PEER; - /* DO NOT close: we might still write! */ - } - - if (ev & PICO_SOCK_EV_FIN) { - /* DO NOT set ep->s = NULL, we might still be transmitting stuff! */ - ep->state = SOCK_CLOSED; - } - - pico_signal_send(pico_signal_select); /* Signal this event globally (e.g. for select()) */ - pico_signal_send(ep->signal); /* Signal the endpoint that was blocking on this event */ - - pico_mutex_unlock(ep->mutex_lock); -} - - -#define DNSQUERY_OK 1 -#define DNSQUERY_FAIL 0xFF -struct dnsquery_cookie -{ - struct addrinfo **res; - void *signal; - uint8_t block; - uint8_t revents; -}; - -static struct dnsquery_cookie *dnsquery_cookie_create(struct addrinfo **res, uint8_t block) -{ - struct dnsquery_cookie *ck = PICO_ZALLOC(sizeof(struct dnsquery_cookie)); - if (!ck) { - pico_err = PICO_ERR_ENOMEM; - errno = pico_err; - return NULL; - } - ck->signal = pico_signal_init(); - ck->res = res; - ck->block = block; - return ck; -} - -static int dnsquery_cookie_delete(struct dnsquery_cookie *ck) -{ - if (!ck) { - pico_err = PICO_ERR_EINVAL; - errno = pico_err; - return -1; - } - if (ck->signal) - { - pico_signal_deinit(ck->signal); - ck->signal = NULL; - } - PICO_FREE(ck); - return 0; -} - -#ifdef PICO_SUPPORT_IPV6 -static void dns_ip6_cb(char *ip, void *arg) -{ - struct dnsquery_cookie *ck = (struct dnsquery_cookie *)arg; - struct addrinfo *new; - - if (ip) { - new = PICO_ZALLOC(sizeof(struct addrinfo)); - if (!new) { - ck->revents = DNSQUERY_FAIL; - if (ck->block) - pico_signal_send(ck->signal); - return; - } - new->ai_family = AF_INET6; - new->ai_addr = PICO_ZALLOC(sizeof(struct sockaddr_in6)); - if (!new->ai_addr) { - PICO_FREE(new); - ck->revents = DNSQUERY_FAIL; - if (ck->block) - pico_signal_send(ck->signal); - return; - } - new->ai_addrlen = sizeof(struct sockaddr_in6); - pico_string_to_ipv6(ip, (((struct sockaddr_in6*)(new->ai_addr))->sin6_addr.s6_addr)); - ((struct sockaddr_in6*)(new->ai_addr))->sin6_family = AF_INET6; - new->ai_next = *ck->res; - *ck->res = new; - ck->revents = DNSQUERY_OK; - } else { - /* No ip given, but still callback was called: timeout! */ - ck->revents = DNSQUERY_FAIL; - } - - if (ck->block) - pico_signal_send(ck->signal); -} -#endif - -static void dns_ip4_cb(char *ip, void *arg) -{ - struct dnsquery_cookie *ck = (struct dnsquery_cookie *)arg; - struct addrinfo *new; - if (ip) { - new = PICO_ZALLOC(sizeof(struct addrinfo)); - if (!new) { - ck->revents = DNSQUERY_FAIL; - if (ck->block) - pico_signal_send(ck->signal); - return; - } - new->ai_family = AF_INET; - new->ai_addr = PICO_ZALLOC(sizeof(struct sockaddr_in)); - if (!new->ai_addr) { - PICO_FREE(new); - ck->revents = DNSQUERY_FAIL; - if (ck->block) - pico_signal_send(ck->signal); - return; - } - new->ai_addrlen = sizeof(struct sockaddr_in); - pico_string_to_ipv4(ip, &(((struct sockaddr_in*)new->ai_addr)->sin_addr.s_addr)); - ((struct sockaddr_in*)(new->ai_addr))->sin_family = AF_INET; - new->ai_next = *ck->res; - *ck->res = new; - ck->revents = DNSQUERY_OK; - } else { - /* No ip given, but still callback was called: timeout! */ - ck->revents = DNSQUERY_FAIL; - } - if (ck->block) - pico_signal_send(ck->signal); -} - -#ifdef PICO_SUPPORT_DNS_CLIENT -int pico_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) -{ - struct dnsquery_cookie *ck4 = NULL; - struct dnsquery_cookie *ck6 = NULL; - struct sockaddr_in sa4; - *res = NULL; - (void)service; - bsd_dbg("Called pico_getaddrinfo, looking for %s\n", node); - -#ifdef PICO_SUPPORT_IPV6 - struct sockaddr_in6 sa6; - if (pico_string_to_ipv6(node, sa6.sin6_addr.s6_addr) == 0) { - ck6 = dnsquery_cookie_create(res, 0); - dns_ip6_cb((char *)node, ck6); - dnsquery_cookie_delete(ck6); - return 0; - } -#endif - - if (pico_string_to_ipv4(node, &sa4.sin_addr.s_addr) == 0) { - ck4 = dnsquery_cookie_create(res, 0); - dns_ip4_cb((char*)node, ck4); - dnsquery_cookie_delete(ck4); - return 0; - } - -#ifdef PICO_SUPPORT_IPV6 - { - if (!hints || (hints->ai_family == AF_INET6)) { - ck6 = dnsquery_cookie_create(res, 1); - if (!ck6) - return -1; - pico_mutex_lock(picoLock); - if (pico_dns_client_getaddr6(node, dns_ip6_cb, ck6) < 0) - { - bsd_dbg("Error resolving AAAA record %s\n", node); - dnsquery_cookie_delete(ck6); - pico_mutex_unlock(picoLock); - return -1; - } - bsd_dbg("Resolving AAAA record %s\n", node); - pico_mutex_unlock(picoLock); - } - } -#endif /* PICO_SUPPORT_IPV6 */ - - if (!hints || (hints->ai_family == AF_INET)) { - ck4 = dnsquery_cookie_create(res, 1); - pico_mutex_lock(picoLock); - if (pico_dns_client_getaddr(node, dns_ip4_cb, ck4) < 0) - { - bsd_dbg("Error resolving A record %s\n", node); - dnsquery_cookie_delete(ck4); - pico_mutex_unlock(picoLock); - return -1; - } - bsd_dbg("Resolving A record %s\n", node); - pico_mutex_unlock(picoLock); - } - -#ifdef PICO_SUPPORT_IPV6 - if (ck6) { - /* Signal is always sent; either dns resolved, or timeout/failure */ - pico_signal_wait(ck6->signal); - dnsquery_cookie_delete(ck6); - } -#endif /* PICO_SUPPORT_IPV6 */ - - if (ck4) { - /* Signal is always sent; either dns resolved, or timeout/failure */ - pico_signal_wait(ck4->signal); - dnsquery_cookie_delete(ck4); - } - - if (*res) - return 0; - - return -1; -} - -void pico_freeaddrinfo(struct addrinfo *res) -{ - struct addrinfo *cur = res; - struct addrinfo *nxt; - while(cur) { - if (cur->ai_addr) - PICO_FREE(cur->ai_addr); - nxt = cur->ai_next; - PICO_FREE(cur); - cur = nxt; - } -} - -/* Legacy gethostbyname call implementation */ -static struct hostent PRIV_HOSTENT = { }; -struct hostent *pico_gethostbyname(const char *name) -{ - struct addrinfo *res; - struct addrinfo hint = {.ai_family = AF_INET}; - int ret; - if (!PRIV_HOSTENT.h_addr_list) { - /* Done only once: reserve space for 2 entries */ - PRIV_HOSTENT.h_addr_list = PICO_ZALLOC(2 * sizeof(void*)); - PRIV_HOSTENT.h_addr_list[1] = NULL; - } - ret = pico_getaddrinfo(name, NULL, &hint, &res); - if (ret == 0) { - if (PRIV_HOSTENT.h_name != NULL) { - PICO_FREE(PRIV_HOSTENT.h_name); - PRIV_HOSTENT.h_name = NULL; - } - if (PRIV_HOSTENT.h_addr_list[0] != NULL) { - PICO_FREE(PRIV_HOSTENT.h_addr_list[0]); - PRIV_HOSTENT.h_addr_list[0] = NULL; - } - PRIV_HOSTENT.h_name = PICO_ZALLOC(strlen(name)); - if (!PRIV_HOSTENT.h_name) { - pico_freeaddrinfo(res); - return NULL; - } - strcpy(PRIV_HOSTENT.h_name, name); - PRIV_HOSTENT.h_addrtype = res->ai_addr->sa_family; - if (PRIV_HOSTENT.h_addrtype == AF_INET) { - PRIV_HOSTENT.h_length = 4; - PRIV_HOSTENT.h_addr_list[0] = PICO_ZALLOC(4); - if (!PRIV_HOSTENT.h_addr_list[0]) { - pico_freeaddrinfo(res); - return NULL; - } - memcpy (PRIV_HOSTENT.h_addr_list[0], &(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr), 4); - } else { - /* Only IPv4 supported by this ancient call. */ - pico_freeaddrinfo(res); - return NULL; - } - pico_freeaddrinfo(res); - return &PRIV_HOSTENT; - } - return NULL; -} -#endif - -int pico_getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) -{ - struct pico_bsd_endpoint *ep = get_endpoint(sockfd, 1); - int ret; - bsd_dbg("called getsockopt\n"); - VALIDATE_NULL(ep); - if (level != SOL_SOCKET) { - pico_err = PICO_ERR_EPROTONOSUPPORT; - errno = pico_err; - return -1; - } - if (!ep) { - pico_err = PICO_ERR_EINVAL; - errno = pico_err; - return -1; - } - if (!optval) { - pico_err = PICO_ERR_EFAULT; - errno = pico_err; - return -1; - } - - if (optname == SO_ERROR) - { - *((int*)optval) = ep->error; - ep->error = 0; - return 0; - } - - pico_mutex_lock(ep->mutex_lock); - ret = pico_socket_getoption(ep->s, sockopt_get_name(optname), optval); - pico_mutex_unlock(ep->mutex_lock); - return ret; - -} - -int pico_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) -{ - - struct pico_bsd_endpoint *ep = get_endpoint(sockfd, 1); - int ret; - VALIDATE_NULL(ep); - ep->error = PICO_ERR_NOERR; - bsd_dbg("called setsockopt\n"); - if (level != SOL_SOCKET) { - pico_err = PICO_ERR_EPROTONOSUPPORT; - errno = pico_err; - return -1; - } - if (!ep) { - pico_err = PICO_ERR_EINVAL; - errno = pico_err; - return -1; - } - if (!optval) { - pico_err = PICO_ERR_EFAULT; - errno = pico_err; - return -1; - } - if ((optname == SO_REUSEADDR) || (optname == SO_REUSEPORT)) - return 0; /* Pretend it was OK. */ - if (optname == SO_ERROR) - return PICO_ERR_ENOPROTOOPT; - - pico_mutex_lock(ep->mutex_lock); - ret = pico_socket_setoption(ep->s, sockopt_get_name(optname), (void *)optval); - pico_mutex_unlock(ep->mutex_lock); - return ret; -} -#ifdef PICO_SUPPORT_SNTP_CLIENT -int pico_gettimeofday(struct timeval *tv, struct timezone *tz) -{ - int ret; - (void)tz; - struct pico_timeval ptv; - - ret= pico_sntp_gettimeofday(&ptv); - - tv->tv_sec = ptv.tv_sec; - tv->tv_usec= ptv.tv_msec * 1000; /* pico_timeval uses milliseconds instead of microseconds */ - return ret; -} - -/* dummy function */ -int pico_settimeofday(struct timeval *tv, struct timezone *tz) -{ - (void)tz; - (void)tv; - return 0; -} - -#else - -static struct pico_timeval ptv = {0u,0u}; - -int pico_gettimeofday(struct timeval *tv, struct timezone *tz) -{ - int ret; - (void)tz; - - tv->tv_sec = ptv.tv_sec; - tv->tv_usec= ptv.tv_msec * 1000; /* pico_timeval uses milliseconds instead of microseconds */ - return 0; -} - -int pico_settimeofday(struct timeval *tv, struct timezone *tz) -{ - int ret; - (void)tz; - - ptv.tv_sec = tv->tv_sec; - ptv.tv_msec= tv->tv_usec / 1000; /* pico_timeval uses milliseconds instead of microseconds */ - return 0; -} -#endif - -long XTIME(void) { - struct timeval t; - pico_gettimeofday(&t, NULL); - return (long)t.tv_sec; -} - -const char *pico_inet_ntop(int af, const void *src, char *dst, socklen_t size) -{ - if ((!dst) || (!src)) - return NULL; - - switch (af) - { - case AF_INET: - if (size < INET_ADDRSTRLEN) - return NULL; - pico_ipv4_to_string(dst, *((const uint32_t *)src)); - break; -#ifdef PICO_SUPPORT_IPV6 - case AF_INET6: - if (size < INET6_ADDRSTRLEN) - return NULL; - pico_ipv6_to_string(dst, ((struct in6_addr *)src)->s6_addr); - break; -#endif - default: - dst = NULL; - break; - } - return dst; -} - -char *pico_inet_ntoa(struct in_addr in) -{ - static char ipbuf[INET_ADDRSTRLEN]; - pico_ipv4_to_string(ipbuf, (uint32_t)in.s_addr); - return ipbuf; -} - - - -int pico_pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask) -{ - /* - * EV_READ: sets the readfds - * EV_WRITE: sets the writefds - * EV_CONN: sets the readfds (a.k.a. someone connects to your listening socket) - * EV_CLOSE: sets the readfds, then next recv() returns 0; - * EV_FIN: sets the readfds, then next recv() returns 0; - * EV_ERR: sets the exceptfds - */ - - int i = 0; /* socket fds */ - int nfds_out = 0; /* amount of changed sockets */ - (void) sigmask; - - bsd_dbg_select("=== IN: PICO SELECT === readfds[0]: 0x%x -- writefds[0]: 0x%x\n", readfds?(*(uint8_t *)readfds):0, writefds?(*(uint8_t *)writefds):0); - - pico_fd_set readfds_out = {}; - pico_fd_set writefds_out = {}; - pico_fd_set exceptfds_out = {}; - /* First, loop over all possible file descriptors, check if one has an event pending that we're waiting for */ - while (nfds_out == 0) - { - for (i = 0; i < nfds; i++) - { - struct pico_bsd_endpoint *ep = get_endpoint(i, 0); - bsd_dbg_select("\t~~~ SELECT: fds %d - ep:%p ", i, ep); - if (ep) - { - /* Is this endpoint still valid? */ - if (!ep->in_use) - { - bsd_dbg_select(" ep->in_use = 0\n"); - break; - } - - /* READ event needed and available? */ - if (readfds && PICO_FD_ISSET(i,readfds) && (ep->revents & (PICO_SOCK_EV_CONN | PICO_SOCK_EV_CLOSE | PICO_SOCK_EV_RD))) - { - bsd_dbg_select("- READ_EV - "); - nfds_out++; - PICO_FD_SET(i, &readfds_out); - } - - /* Force write events on empty udp sockets */ - if ((ep->proto == PICO_PROTO_UDP) && (ep->s->q_out.size < ep->s->q_out.max_size)) - ep->revents |= PICO_SOCK_EV_WR; - - /* WRITE event needed? and available? */ - if (writefds && PICO_FD_ISSET(i,writefds) && (ep->revents & (PICO_SOCK_EV_WR))) - { - bsd_dbg_select("- WRITE_EV - "); - nfds_out++; - PICO_FD_SET(i, &writefds_out); - } - - /* EXCEPTION event needed and available? */ - if (exceptfds && PICO_FD_ISSET(i,exceptfds) && (ep->revents & (PICO_SOCK_EV_ERR))) - { - bsd_dbg_select("- EXCEPT_EV - "); - nfds_out++; - PICO_FD_SET(i, &exceptfds_out); - } - } - - if (ep) - bsd_dbg_select("- s:%p - ev:%x", ep->s, ep->revents); - bsd_dbg_select("\n"); - } - - /* If there was a hit, break out of the loop */ - if (nfds_out) - break; - - /* If not, wait for a semaphore signaling an event from the stack */ - if (pico_signal_wait_timeout(pico_signal_select, (timeout->tv_sec * 1000) + ((timeout->tv_nsec) / 1000000)) == -1) - { - /* On timeout, break out of the loop */ - bsd_dbg_select("\t~~~ SELECT: TIMEOUT\n"); - break; - } else { - /* Process the received event -> re-iterate */ - bsd_dbg_select("\t~~~ SELECT: Socket event, re-iterating fds\n"); - } - } - - /* Copy back result only if descriptor was valid */ - if (readfds) - memcpy(readfds, &readfds_out, sizeof(pico_fd_set)); - if (writefds) - memcpy(writefds, &writefds_out, sizeof(pico_fd_set)); - if (exceptfds) - memcpy(exceptfds, &exceptfds_out, sizeof(pico_fd_set)); - - bsd_dbg_select("=== OUT: PICO SELECT === fds changed: %d\n", nfds_out); - - return nfds_out; -} - -int pico_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -{ - struct timespec ts; - if (timeout) { - ts.tv_sec = timeout->tv_sec; - ts.tv_nsec = timeout->tv_usec * 1000; - return pico_pselect(nfds, readfds, writefds, exceptfds, &ts, NULL); - } else - return pico_pselect(nfds, readfds, writefds, exceptfds, NULL, NULL); -} - -int pico_ppoll(struct pollfd *pfd, nfds_t npfd, const struct timespec *timeout, const sigset_t *sigmask) { - int i; - int ret = 0; - (void) sigmask; - - while (ret == 0) { - for (i = 0; i < npfd; i++) { - struct pico_bsd_endpoint *ep = get_endpoint(pfd[i].fd, 0); - pfd[i].revents = 0u; - - /* Always polled events */ - if (!ep) { - pfd[i].revents |= POLLNVAL; - } - if (!ep->in_use) { - pfd[i].revents |= POLLNVAL; - } - if (ep->revents & (PICO_SOCK_EV_FIN | PICO_SOCK_EV_ERR)) { - pfd[i].revents |= POLLERR; - ret++; - } - if (ep->revents & PICO_SOCK_EV_CLOSE) - pfd[i].revents |= POLLHUP; /* XXX: I am sure we mean POLLRDHUP ! see man 2 poll */ - - /* Checking POLLIN */ - if ((pfd[i].events & POLLIN) && (ep->revents & (PICO_SOCK_EV_RD | PICO_SOCK_EV_CONN))) { - pfd[i].revents |= POLLIN; - if (pfd[i].events & POLLRDNORM) - pfd[i].revents |= POLLRDNORM; - } - /* Checking POLLOUT */ - if ((pfd[i].events & POLLOUT) && (ep->revents & (PICO_SOCK_EV_WR))) { - pfd[i].revents |= POLLOUT; - if (pfd[i].events & POLLWRNORM) - pfd[i].revents |= POLLWRNORM; - } - - if (pfd[i].revents != 0) - ret++; - } /* End for loop */ - if ((ret == 0) && timeout && (pico_signal_wait_timeout(pico_signal_select, (timeout->tv_sec * 1000) + ((timeout->tv_nsec) / 1000000)) == -1)) - return 0; /* Timeout */ - } /* End while loop */ - return ret; -} - -int pico_poll(struct pollfd *pfd, nfds_t npfd, int timeout) -{ - struct timespec ts = {0U, 0U}; - if (timeout >= 0) { - ts.tv_sec = timeout / 1000; - ts.tv_nsec = (timeout % 1000) * 1000000; - return pico_ppoll(pfd, npfd, &ts, NULL); - } else { - return pico_ppoll(pfd, npfd, NULL, NULL); - } -} diff --git a/ext/pico_bsd/pico_bsd_sockets.h b/ext/pico_bsd/pico_bsd_sockets.h deleted file mode 100644 index e8e2198..0000000 --- a/ext/pico_bsd/pico_bsd_sockets.h +++ /dev/null @@ -1,331 +0,0 @@ -/********************************************************************* -PicoTCP. Copyright (c) 2013 TASS Belgium NV. Some rights reserved. -See LICENSE and COPYING for usage. -Do not redistribute without a written permission by the Copyright -holders. - -Author: Maxime Vincent, Daniele Lacamera -*********************************************************************/ -#ifndef PICO_BSD_SOCKETS_H_ -#define PICO_BSD_SOCKETS_H_ - -#include -#include -#include "pico_defines.h" -#include "pico_constants.h" -#include "pico_config.h" -#include "pico_stack.h" -#include "pico_icmp4.h" -#include "pico_stack.h" -#include "pico_ipv4.h" -#include "pico_ipv6.h" -#include "pico_dns_client.h" -#include "pico_socket.h" - -#define SOCKSIZE 16 -#define SOCKSIZE6 28 - -struct pico_bsd_endpoint; -extern void *picoLock; -extern void *pico_signal_tick; - -#if defined STDSOCKET || defined __socklen_t_defined - #include - #include - #include - #include - #include - #include - #include - #ifdef __linux__ - #include - #endif - - static inline int sockopt_get_name(int posix_name) - { - switch (posix_name) { - case IP_MULTICAST_LOOP: return PICO_IP_MULTICAST_LOOP; - case IP_MULTICAST_TTL: return PICO_IP_MULTICAST_TTL; - case IP_MULTICAST_IF: return PICO_IP_MULTICAST_IF; - case IP_ADD_MEMBERSHIP: return PICO_IP_ADD_MEMBERSHIP; - case IP_DROP_MEMBERSHIP: return PICO_IP_DROP_MEMBERSHIP; - case SO_RCVBUF : return PICO_SOCKET_OPT_RCVBUF; - case SO_SNDBUF : return PICO_SOCKET_OPT_SNDBUF; - case TCP_NODELAY : return PICO_TCP_NODELAY; - case TCP_KEEPCNT : return PICO_SOCKET_OPT_KEEPCNT; - case TCP_KEEPIDLE : return PICO_SOCKET_OPT_KEEPIDLE; - case TCP_KEEPINTVL : return PICO_SOCKET_OPT_KEEPINTVL; - } - return -1; - } - - #define pico_fd_set fd_set - #define PICO_FD_SET FD_SET - #define PICO_FD_CLR FD_CLR - #define PICO_FD_ISSET FD_ISSET - #define PICO_FD_ZERO FD_ZERO - - #undef fcntl - #define fcntl pico_fcntl - -#else - typedef int socklen_t; - #define AF_INET (PICO_PROTO_IPV4) - #define AF_INET6 (PICO_PROTO_IPV6) - #define SOCK_STREAM (PICO_PROTO_TCP) - #define SOCK_DGRAM (PICO_PROTO_UDP) - - #define SOL_SOCKET (0x80) - - #define IP_MULTICAST_LOOP (PICO_IP_MULTICAST_LOOP) - #define IP_MULTICAST_TTL (PICO_IP_MULTICAST_TTL) - #define IP_MULTICAST_IF (PICO_IP_MULTICAST_IF) - #define IP_ADD_MEMBERSHIP (PICO_IP_ADD_MEMBERSHIP) - #define IP_DROP_MEMBERSHIP (PICO_IP_DROP_MEMBERSHIP) - #define SO_RCVBUF (PICO_SOCKET_OPT_RCVBUF) - #define SO_SNDBUF (PICO_SOCKET_OPT_SNDBUF) - #define TCP_NODELAY (PICO_TCP_NODELAY) - #define TCP_KEEPCNT (PICO_SOCKET_OPT_KEEPCNT) - #define TCP_KEEPIDLE (PICO_SOCKET_OPT_KEEPIDLE) - #define TCP_KEEPINTVL (PICO_SOCKET_OPT_KEEPINTVL) - #define SO_ERROR (4103) - #define SO_REUSEADDR (2) - #define sockopt_get_name(x) ((x)) - - #define INET_ADDRSTRLEN (16) - #define INET6_ADDRSTRLEN (46) - - struct sockaddr { - uint16_t sa_family; - }; - - struct in_addr { - uint32_t s_addr; - }; - - #define INADDR_ANY ((uint32_t)0U) - - struct in6_addr { - uint8_t s6_addr[16]; - }; - - struct __attribute__((packed)) sockaddr_in { - uint16_t sin_family; - uint16_t sin_port; - struct in_addr sin_addr; - uint8_t _pad[SOCKSIZE - 8]; - }; - - - struct __attribute__((packed)) sockaddr_in6 { - uint16_t sin6_family; - uint16_t sin6_port; - uint32_t sin6_flowinfo; - struct in6_addr sin6_addr; - uint32_t sin6_scope_id; - }; - - struct __attribute__((packed)) sockaddr_storage { - uint16_t ss_family; - uint8_t _pad[(SOCKSIZE6 - sizeof(uint16_t))]; - }; - - /* getaddrinfo */ - struct addrinfo { - int ai_flags; - int ai_family; - int ai_socktype; - int ai_protocol; - socklen_t ai_addrlen; - struct sockaddr *ai_addr; - char *ai_canonname; - struct addrinfo *ai_next; - }; - - - /* hostent */ - struct hostent { - char *h_name; /* official name of host */ - char **h_aliases; /* alias list */ - int h_addrtype; /* host address type */ - int h_length; /* length of address */ - char **h_addr_list; /* list of addresses */ - }; - #define h_addr h_addr_list[0] /* for backward compatibility */ - - /* fd_set */ - #ifndef FD_SETSIZE - #define FD_SETSIZE 64 /* 64 files max, 1 bit per file -> 64bits = 8 bytes */ - #endif - - struct pico_fd_set_s { - uint8_t fds_bits[FD_SETSIZE/8]; - }; - - typedef struct pico_fd_set_s pico_fd_set; - #ifndef fd_set - #define fd_set pico_fd_set - #endif - - //typedef void sigset_t; - - #define PICO_FD_SET(n, p) ((p)->fds_bits[(n)/8] |= (1u << ((n) % 8))) - #define PICO_FD_CLR(n, p) ((p)->fds_bits[(n)/8] &= ~(1u << ((n) % 8))) - #define PICO_FD_ISSET(n, p) ((p)->fds_bits[(n)/8] & (1u << ((n) % 8))) - #define PICO_FD_ZERO(p) do{memset((p)->fds_bits, 0, sizeof(struct pico_fd_set_s));}while(0) - - /* Not socket related */ - #ifndef __time_t_defined - typedef pico_time time_t; - #define __time_t_defined - #endif - - #if !defined _TIME_H && !defined _TIMEVAL_DEFINED && !defined _STRUCT_TIMEVAL - struct timeval { - time_t tv_sec; - time_t tv_usec; - }; - - #if !defined __timespec_defined && !defined _SYS__TIMESPEC_H_ - struct timespec { - long tv_sec; - long tv_nsec; - }; - #endif - - struct timezone { - int tz_minuteswest; /* minutes west of Greenwich */ - int tz_dsttime; /* type of DST correction */ - }; - #define _TIMEVAL_DEFINED - #endif -#endif /* STDSOCKET */ - -#ifndef SO_REUSEPORT - #define SO_REUSEPORT (15) -#endif - -#ifndef FD_CLOEXEC - #define FD_CLOEXEC 1 -#endif - -#ifndef F_DUPFD - #define F_DUPFD 0 -#endif - -#ifndef F_GETFD - #define F_GETFD 1 -#endif - -#ifndef F_SETFD - #define F_SETFD 2 -#endif - -#ifndef F_GETFL - #define F_GETFL 3 -#endif - -#ifndef F_SETFL - #define F_SETFL 4 -#endif - - -#ifndef O_NONBLOCK - #define O_NONBLOCK 0x4000 -#endif - -#ifndef _SYS_POLL_H - #define POLLIN 0x001 /* There is data to read. */ - #define POLLPRI 0x002 /* There is urgent data to read. */ - #define POLLOUT 0x004 /* Writing now will not block. */ - #define POLLRDNORM 0x040 /* Normal data may be read. */ - #define POLLRDBAND 0x080 /* Priority data may be read. */ - #define POLLWRNORM 0x100 /* Writing now will not block. */ - #define POLLWRBAND 0x200 /* Priority data may be written. */ - - #define POLLMSG 0x400 - #define POLLREMOVE 0x1000 - #define POLLRDHUP 0x2000 - - #define POLLERR 0x008 /* Error condition. */ - #define POLLHUP 0x010 /* Hung up. */ - #define POLLNVAL 0x020 /* Invalid polling request. */ - - typedef unsigned long int nfds_t; - - struct pollfd { - int fd; - uint16_t events; - uint16_t revents; - }; -#endif - -int pico_newsocket(int domain, int type, int proto); -int pico_bind(int sd, struct sockaddr * local_addr, socklen_t socklen); -int pico_listen(int sd, int backlog); -int pico_connect(int sd, struct sockaddr *_saddr, socklen_t socklen); -int pico_isconnected(int sd); -int pico_accept(int sd, struct sockaddr *_orig, socklen_t *socklen); -int pico_sendto(int sd, void * buf, int len, int flags, struct sockaddr *_dst, socklen_t socklen); -int pico_recvfrom(int sd, void * buf, int len, int flags, struct sockaddr *_addr, socklen_t *socklen); -int pico_write(int sd, void * buf, int len); -int pico_send(int sd, void * buf, int len, int flags); -int pico_read(int sd, void * buf, int len); -int pico_recv(int sd, void * buf, int len, int flags); -int pico_close(int sd); -int pico_shutdown(int sd, int how); -int pico_getsockname(int sd, struct sockaddr * local_addr, socklen_t *socklen); -int pico_getpeername(int sd, struct sockaddr * remote_addr, socklen_t *socklen); -int pico_fcntl(int sd, int cmd, int arg); -int pico_join_multicast_group(int sd, const char *address, const char *local); - -#ifdef PICO_SUPPORT_DNS_CLIENT - struct hostent *pico_gethostbyname(const char *name); - - /* getaddrinfo */ - int pico_getaddrinfo(const char *node, const char *service, - const struct addrinfo *hints, - struct addrinfo **res); - - void pico_freeaddrinfo(struct addrinfo *res); -#endif - -int pico_setsockopt (int sockfd, int level, int optname, const void *optval, socklen_t optlen); -int pico_getsockopt (int sockfd, int level, int optname, void *optval, socklen_t *optlen); - -int pico_select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); -int pico_pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, - const sigset_t *sigmask); - -int pico_poll (struct pollfd *pfd, nfds_t npfd, int timeout); -int pico_ppoll (struct pollfd *pfd, nfds_t npfd, const struct timespec *timeout_ts, const sigset_t *sigmask); - -#ifndef PICO_SUPPORT_SNTP_CLIENT - struct pico_timeval - { - pico_time tv_sec; - pico_time tv_msec; - }; - int pico_settimeofday(struct timeval *tv, struct timezone *tz); -#endif - -int pico_gettimeofday(struct timeval *tv, struct timezone *tz); -long XTIME(void); -#define XGMTIME gmtime - -/* arpa/inet.h */ -const char *pico_inet_ntop (int af, const void *src, char *dst, socklen_t size); -char *pico_inet_ntoa (struct in_addr in); - -/* Non-POSIX */ -void pico_bsd_init(void); -void pico_bsd_deinit(void); -void pico_bsd_stack_tick(void); -void pico_bsd_stack_tick_timeout(int timeout_ms); -uint16_t pico_bsd_select(struct pico_bsd_endpoint *ep); - -#ifdef REPLACE_STDCALLS - #include "pico_bsd_syscalls.h" -#endif - -#endif /* PICO_BSD_SOCKETS_H_ */ diff --git a/ext/pico_bsd/pico_bsd_syscalls.h b/ext/pico_bsd/pico_bsd_syscalls.h deleted file mode 100644 index 177012c..0000000 --- a/ext/pico_bsd/pico_bsd_syscalls.h +++ /dev/null @@ -1,336 +0,0 @@ -#ifndef PICO_BSD_SYSCALLS_H_ -#define PICO_BSD_SYSCALLS_H_ - -#include "pico_bsd_sockets.h" - -/* Cannot be included directly, expect from pico_bsd_sockets.h */ - -#if defined (__socklen_t_defined) && defined (REPLACE_STDCALLS) - - /* For systems that have the syscalls already defined */ - #ifdef socket - #undef socket - #endif - #define socket pico_newsocket - - #ifdef bind - #undef bind - #endif - #define bind pico_bind - - #ifdef listen - #undef listen - #endif - #define listen pico_listen - - #ifdef connect - #undef connect - #endif - #define connect pico_connect - - #ifdef accept - #undef accept - #endif - #define accept pico_accept - - #ifdef sendto - #undef sendto - #endif - #define sendto pico_sendto - - #ifdef recvfrom - #undef recvfrom - #endif - #define recvfrom pico_recvfrom - - #ifdef write - #undef write - #endif - #define write pico_write - - #ifdef read - #undef read - #endif - #define read pico_read - - #ifdef send - #undef send - #endif - #define send pico_send - - #ifdef recv - #undef recv - #endif - #define recv pico_recv - - #ifdef close - #undef close - #endif - #define close pico_close - - #ifdef shutdown - #undef shutdown - #endif - #define shutdown pico_shutdown - - #ifdef getsockname - #undef getsockname - #endif - #define getsockname pico_getsockname - - #ifdef getpeername - #undef getpeername - #endif - #define getpeername pico_getpeername - - #ifdef setsockopt - #undef setsockopt - #endif - #define setsockopt pico_setsockopt - - #ifdef getsockopt - #undef getsockopt - #endif - #define getsockopt pico_getsockopt - - #ifdef gettimeofday - #undef gettimeofday - #endif - #define gettimeofday pico_gettimeofday - - #ifdef gethostbyname - #undef gethostbyname - #endif - #define gethostbyname pico_gethostbyname - - #ifdef getaddrinfo - #undef getaddrinfo - #endif - #define getaddrinfo pico_getaddrinfo - - #ifdef freeaddrinfo - #undef freeaddrinfo - #endif - #define freeaddrinfo pico_freeaddrinfo - - #ifdef htons - #undef htons - #endif - #define htons short_be - - #ifdef htonl - #undef htonl - #endif - #define htonl long_be - - #ifdef ntohs - #undef ntohs - #endif - #define ntohs short_be - - #ifdef ntohl - #undef ntohl - #endif - #define ntohl long_be - - #ifdef inet_ntoa - #undef inet_ntoa - #endif - #define inet_ntoa pico_inet_ntoa - - #ifdef inet_ntop - #undef inet_ntop - #endif - #define inet_ntop pico_inet_ntop - - #ifdef select - #undef select - #endif - #define select pico_select - - #ifdef pselect - #undef pselect - #endif - #define pselect pico_pselect - - #ifdef poll - #undef poll - #endif - #define poll pico_poll - - #ifdef ppoll - #undef ppoll - #endif - #define ppoll pico_ppoll -#else - - static inline int socket(int domain, int type, int proto) - { - return pico_newsocket(domain, type, proto); - } - - static inline int bind(int sd, struct sockaddr * local_addr, socklen_t socklen) - { - return pico_bind(sd, local_addr, socklen); - } - - static inline int listen(int sd, int backlog) - { - return pico_listen(sd, backlog); - } - - static inline int connect(int sd, struct sockaddr *_saddr, socklen_t socklen) - { - return pico_connect(sd, _saddr, socklen); - } - - static inline int accept(int sd, struct sockaddr *_orig, socklen_t *socklen) - { - return pico_accept(sd, _orig, socklen); - } - - static inline int sendto(int sd, void * buf, int len, int flags, struct sockaddr *_dst, socklen_t socklen) - { - return pico_sendto(sd, buf, len, flags, _dst, socklen); - } - - static inline int recvfrom(int sd, void * buf, int len, int flags, struct sockaddr *_addr, socklen_t *socklen) - { - return pico_recvfrom(sd, buf, len, flags, _addr, socklen); - } - - static inline int write(int sd, void * buf, int len) - { - return pico_write(sd, buf, len); - } - - static inline int send(int sd, void * buf, int len, int flags) - { - return pico_send(sd, buf, len, flags); - } - - static inline int read(int sd, void * buf, int len) - { - return pico_read(sd, buf, len); - } - - static inline int recv(int sd, void * buf, int len, int flags) - { - return pico_recv(sd, buf, len, flags); - } - - static inline int close(int sd) - { - return pico_close(sd); - } - - static inline int shutdown(int sd, int how) - { - return pico_shutdown(sd, how); - } - - static inline int getsockname(int sd, struct sockaddr * local_addr, socklen_t *socklen) - { - return pico_getsockname(sd, local_addr, socklen); - } - - static inline int getpeername(int sd, struct sockaddr * remote_addr, socklen_t *socklen) - { - return pico_getpeername(sd, remote_addr, socklen); - } - - static inline int fcntl(int sd, int cmd, int arg) - { - return pico_fcntl(sd, cmd, arg); - } - - #ifdef PICO_SUPPORT_DNS_CLIENT - static inline struct hostent *gethostbyname(const char *name) - { - return pico_gethostbyname(name); - } - - static inline int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) - { - return pico_getaddrinfo(node, service, hints, res); - } - - static inline void freeaddrinfo(struct addrinfo *res) - { - return pico_freeaddrinfo(res); - } - #endif - - static inline int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) - { - return pico_setsockopt(sockfd, level, optname, optval, optlen); - } - - static inline int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) - { - return pico_getsockopt(sockfd, level, optname, optval, optlen); - } - - static inline int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) - { - return pico_select(nfds, readfds, writefds, exceptfds, timeout); - } - - static inline int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask) - { - return pico_pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask); - } - - static inline int poll(struct pollfd *pfd, nfds_t npfd, int timeout) - { - return pico_poll(pfd, npfd, timeout); - } - - static inline int ppoll(struct pollfd *pfd, nfds_t npfd, const struct timespec *timeout_ts, const sigset_t *sigmask) - { - return pico_ppoll(pfd, npfd, timeout_ts, sigmask); - } - - static int gettimeofday(struct timeval *tv, struct timezone *tz) - { - return pico_gettimeofday(tv, tz); - } - - static int settimeofday(struct timeval *tv, struct timezone *tz) - { - return pico_settimeofday(tv, tz); - } - - static inline const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) - { - return pico_inet_ntop(af, src, dst, size); - } - - static inline char *inet_ntoa(struct in_addr in) - { - return pico_inet_ntoa(in); - } - - static inline uint32_t htonl(uint32_t le) - { - return long_be(le); - } - - static inline uint32_t ntohl(uint32_t le) - { - return long_be(le); - } - - static inline uint16_t htons(uint16_t le) - { - return short_be(le); - } - - static inline uint16_t ntohs(uint16_t le) - { - return short_be(le); - } - -#endif - -#endif /* PICO_BSD_SYSCALLS_H_ */ diff --git a/ext/pico_bsd/pico_osal.h b/ext/pico_bsd/pico_osal.h deleted file mode 100644 index 69dd61a..0000000 --- a/ext/pico_bsd/pico_osal.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * pico_osal.h - * - * Created on: December 2013 - * Author: Maxime Vincent - * Description: OS Abstraction Layer between PicoTCP and FreeRTOS - * - */ - -#ifndef _PICO_OSAL_H_ -#define _PICO_OSAL_H_ - -/***************************************************************************** - * Public types/enumerations/variables - ****************************************************************************/ - -/* Queue implementation API is: */ - - -/* Posix version of thread */ -typedef void* pico_thread_t; -typedef void *(*pico_thread_fn)(void *); - -void * pico_mutex_init(void); -void pico_mutex_deinit(void * mutex); -void pico_mutex_lock(void * mutex); -int pico_mutex_lock_timeout(void * mutex, int timeout); -void pico_mutex_unlock(void * mutex); -void pico_mutex_unlock_ISR(void * mutex); - -void * pico_signal_init(void); -void pico_signal_deinit(void * signal); -void pico_signal_wait(void * signal); -int pico_signal_wait_timeout(void * signal, int timeout); -void pico_signal_send(void * signal); -void pico_signal_send_ISR(void * signal); - -pico_thread_t pico_thread_create(pico_thread_fn thread, void *arg, int stack_size, int prio); -void pico_thread_destroy(pico_thread_t t); -void pico_msleep(int ms); - -void pico_threads_schedule(void); - -#endif /* _PICO_OSAL_H_ */ - diff --git a/ext/pico_bsd/pico_osal_freertos.c b/ext/pico_bsd/pico_osal_freertos.c deleted file mode 100644 index bdf41fa..0000000 --- a/ext/pico_bsd/pico_osal_freertos.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * pico_osal.h - * - * Created on: December 2013 - * Author: Maxime Vincent - * Description: OS Abstraction Layer between PicoTCP and FreeRTOS - * - */ -/* FreeRTOS includes */ -#include "FreeRTOS.h" -#include "task.h" -#include "semphr.h" -#include "portmacro.h" - - -/* PicoTCP includes */ -#include "pico_defines.h" -#include "pico_config.h" -#include "pico_osal.h" - -#define osal_dbg(...) -//#define osal_dbg(...) printf(__VA_ARGS__) - -/***************************************************************************** - * Public functions - ****************************************************************************/ - -struct osal_mutex { - void * mutex; - uint8_t idx; /* only to keep track of the amount/idx, no real function .. */ -}; -static uint8_t mtx_number = 0; - - -/* ============= */ -/* == SIGNALS == */ -/* ============= */ - -void * pico_signal_init(void) -{ - struct osal_mutex *signal; - signal = pico_zalloc(sizeof(struct osal_mutex)); - osal_dbg("mi: %p for %p\n", signal, __builtin_return_address(0)); - if (!signal) - return NULL; - signal->mutex= xSemaphoreCreateBinary(); - signal->idx = mtx_number++; - return signal; -} - -void pico_signal_deinit(void * signal) -{ - struct osal_mutex * mtx = signal; - vSemaphoreDelete(mtx->mutex); - pico_free(signal); -} - -void pico_signal_wait(void * signal) -{ - pico_signal_wait_timeout(signal, (int)portMAX_DELAY); -} - -int pico_signal_wait_timeout(void * signal, int timeout) -{ - int retval = 0; - if(signal != NULL) - { - struct osal_mutex * mtx = signal; - if (timeout == portMAX_DELAY) { - while (xSemaphoreTake(mtx->mutex, portMAX_DELAY) == pdFALSE); - } else { - retval = xSemaphoreTake(mtx->mutex, timeout); - } - } - if (retval) { - return 0; /* Success */ - } else { - return -1; /* Timeout */ - } -} - -void pico_signal_send(void * signal) -{ - if(signal != NULL) - { - struct osal_mutex * mtx = signal; - xSemaphoreGive(mtx->mutex); - } -} - -void pico_signal_send_ISR(void * signal) -{ - if(signal != NULL) - { - struct osal_mutex * mtx = signal; - long task_switch_needed = 0; - xSemaphoreGiveFromISR(mtx->mutex, &task_switch_needed); - portYIELD_FROM_ISR(task_switch_needed); - } -} - -/* ============= */ -/* == MUTEXES == */ -/* ============= */ - - -void *pico_mutex_init(void) -{ - struct osal_mutex *mutex; - mutex = pico_zalloc(sizeof(struct osal_mutex)); - osal_dbg("mi: %p for %p\n", mutex, __builtin_return_address(0)); - if (!mutex) - return NULL; - mutex->mutex = xSemaphoreCreateMutex(); - mutex->idx = mtx_number++; - return mutex; -} - -void pico_mutex_deinit(void * mutex) -{ - pico_signal_deinit(mutex); -} - -int pico_mutex_lock_timeout(void * mutex, int timeout) -{ - return pico_signal_wait_timeout(mutex, timeout); -} - -void pico_mutex_lock(void * mutex) -{ - pico_signal_wait_timeout(mutex, (int)portMAX_DELAY); -} - -void pico_mutex_unlock(void * mutex) -{ - pico_signal_send(mutex); -} - -void pico_mutex_unlock_ISR(void * mutex) -{ - pico_signal_send_ISR(mutex); -} - - -/* ============= */ -/* == THREADS == */ -/* ============= */ -static char thread_name[4] = "T"; -static int thread_n = 0; - -pico_thread_t pico_thread_create(pico_thread_fn thread, void *arg, int stack_size, int prio) -{ - pico_thread_t t = PICO_ZALLOC(sizeof(TaskHandle_t)); - if (!t) - return NULL; - thread_name[2] = (thread_n++) % 10; - thread_name[3] = 0; - xTaskCreate((TaskFunction_t)thread, thread_name, stack_size, arg, prio, t); - return t; -} - -void pico_thread_destroy(pico_thread_t t) -{ - vTaskDelete((TaskHandle_t)t); - PICO_FREE(t); -} - -void pico_msleep(int ms) -{ - vTaskDelay(ms); -} - -void pico_threads_schedule(void) -{ - vTaskStartScheduler(); -} diff --git a/ext/pico_bsd/pico_osal_noos.c b/ext/pico_bsd/pico_osal_noos.c deleted file mode 100644 index 2681c9a..0000000 --- a/ext/pico_bsd/pico_osal_noos.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * pico_osal.h - * - * Created on: December 2014 - * Author: Maxime Vincent - * Description: OS Abstraction Layer between PicoTCP and No Operating System - * - */ - -/* PicoTCP includes */ -#include "pico_defines.h" -#include "pico_config.h" -#include "pico_stack.h" -#include "pico_osal.h" - -#define osal_dbg(...) -//#define osal_dbg(...) printf(__VA_ARGS__) - -/***************************************************************************** - * Public functions - ****************************************************************************/ - -/* ============= */ -/* == MUTEXES == */ -/* ============= */ - -struct osal_mutex { - volatile int want_to_take; /* for ISR safety, basically a mutex for the mutex */ - volatile int mutex; - int idx; /* only to keep track of the amount/idx, no real function .. */ -}; - -static uint8_t mtx_number = 0; - -void * pico_mutex_init(void) -{ - struct osal_mutex * mutex; - mutex = pico_zalloc(sizeof(struct osal_mutex)); - osal_dbg("mi: %p for %p\n", mutex, __builtin_return_address(0)); - if (!mutex) - return NULL; - mutex->mutex = 1; - mutex->idx = mtx_number++; - return mutex; -} - -void pico_mutex_deinit(void * mutex) -{ - struct osal_mutex * mtx = mutex; - pico_free(mutex); -} - -int pico_mutex_lock_timeout(void * mutex, int timeout) -{ - int retval = 0; - if(mutex != NULL) - { - struct osal_mutex * mtx = mutex; - pico_time timestamp = PICO_TIME_MS(); - while (mtx->mutex == 0) - { - pico_stack_tick(); - #ifdef _POSIX_VERSION - usleep(500); - #endif - - /* break on timeout unless infinite timeout */ - if ((timeout != -1) && (PICO_TIME_MS() > (timestamp + timeout))) - break; - } - if (mtx->mutex == 1) - { - mtx->mutex = 0; /* take the mutex */ - } - else - { - retval = -1; /* timeout */ - } - } - return retval; -} - -void pico_mutex_lock(void * mutex) -{ - pico_mutex_lock_timeout(mutex, -1); -} - -void pico_mutex_unlock(void * mutex) -{ - if(mutex != NULL) - { - struct osal_mutex * mtx = mutex; - mtx->mutex = 1; - } -} - -void pico_mutex_unlock_ISR(void * mutex) -{ - if(mutex != NULL) - { - struct osal_mutex * mtx = mutex; - // tricky stuff needed or not? - mtx->mutex = 1; - } -} - -/* ============= */ -/* == SIGNALS == */ -/* ============= */ - -void * pico_signal_init(void) -{ - void * signal = pico_mutex_init(); - pico_mutex_lock(signal); - return signal; -} - -void pico_signal_deinit(void * signal) -{ - pico_mutex_deinit(signal); -} - -void pico_signal_wait(void * signal) -{ - pico_signal_wait_timeout(signal, -1); -} - -int pico_signal_wait_timeout(void * signal, int timeout) -{ - return pico_mutex_lock_timeout(signal, timeout); -} - -void pico_signal_send(void * signal) -{ - pico_mutex_unlock(signal); -} - -void pico_signal_send_ISR(void * signal) -{ - pico_mutex_unlock_ISR(signal); -} - - -/* ============= */ -/* == THREADS == */ -/* ============= */ - -pico_thread_t pico_thread_create(pico_thread_fn thread, void *arg, int stack_size, int prio) -{ - (void)thread; - (void)arg; - (void)stack_size; - (void)prio; - return NULL; -} - -void pico_thread_destroy(pico_thread_t t) -{ - return; -} - -void pico_msleep(int ms) -{ - pico_time now = PICO_TIME_MS(); - while ((pico_time)(now + ms) < PICO_TIME_MS()); -} diff --git a/ext/pico_bsd/pico_osal_pthread.c b/ext/pico_bsd/pico_osal_pthread.c deleted file mode 100644 index e02c882..0000000 --- a/ext/pico_bsd/pico_osal_pthread.c +++ /dev/null @@ -1,119 +0,0 @@ -/* Pthread osal implementation, for testing purposes */ -#include -#include "pico_defines.h" -#include "pico_stack.h" -#include "pico_osal.h" -#include -#include - -#define BILLION 1000000000 - -void * pico_mutex_init(void) { - pthread_mutex_t *mutex = pico_zalloc(sizeof(pthread_mutex_t)); - if (!mutex) - return NULL; - if (pthread_mutex_init(mutex, NULL) == 0 ) - return mutex; - pico_free(mutex); - return NULL; -} -void pico_mutex_deinit(void * mutex) -{ - pthread_mutex_destroy((pthread_mutex_t *)mutex); - pico_free(mutex); -} - -void pico_mutex_lock(void * mutex) -{ - pthread_mutex_lock((pthread_mutex_t *)mutex); -} - -int pico_mutex_lock_timeout(void *mutex, int timeout) -{ - if (timeout < 0) { - return pthread_mutex_lock((pthread_mutex_t *)mutex); - - } else { - struct timespec ts = { timeout / 1000, (timeout % 1000) * 1000000 }; - return pthread_mutex_timedlock((pthread_mutex_t *)mutex, &ts); - } - -} - -void pico_mutex_unlock(void * mutex) -{ - pthread_mutex_unlock((pthread_mutex_t *)mutex); -} - - -void * pico_signal_init(void) -{ - sem_t *sem = pico_zalloc(sizeof(pthread_mutex_t)); - if (!sem) - return NULL; - if (sem_init(sem, 0, 0) == 0) - return sem; - pico_free(sem); - return NULL; -} - -void pico_signal_deinit(void * signal) -{ - sem_destroy((sem_t *) signal); -} - -void pico_signal_wait(void * signal) -{ - sem_wait((sem_t *) signal); -} - -int pico_signal_wait_timeout(void * signal, int timeout) -{ - if (timeout < 0) { - return sem_wait((sem_t *) signal); - } else { - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += (timeout / 1000); - ts.tv_nsec += ((timeout % 1000) * 1000000); - if (ts.tv_nsec >= BILLION) { - ts.tv_nsec -= BILLION; - ts.tv_sec++; - } - return sem_timedwait((sem_t *) signal, &ts); - } -} - -void pico_signal_send(void * signal) -{ - sem_post((sem_t *) signal); -} - -pico_thread_t pico_thread_create(pico_thread_fn thread, void *arg, int stack_size, int prio) -{ - pico_thread_t t = PICO_ZALLOC(sizeof(pthread_t)); - if (!t) - return NULL; - (void)stack_size; - (void)prio; - pthread_create((pthread_t *)t, NULL, thread, arg); - pthread_detach(*((pthread_t *)t)); -} - -void pico_thread_destroy(pico_thread_t t) -{ - pthread_cancel(*((pthread_t *)t)); - PICO_FREE(t); -} - -void pico_msleep(int ms) -{ - struct timespec ts = { ms / 1000, (ms % 1000) * 1000000 }; - nanosleep(&ts, NULL); -} - -void pico_threads_schedule(void) -{ - while (1 < 2) - pico_msleep(1000); -} diff --git a/ext/pico_bsd/pico_posix_wrapper.c b/ext/pico_bsd/pico_posix_wrapper.c deleted file mode 100644 index a376753..0000000 --- a/ext/pico_bsd/pico_posix_wrapper.c +++ /dev/null @@ -1,429 +0,0 @@ -#include "pico_bsd_sockets.h" -#define _GNU_SOURCE -#define __GNU_SOURCE -#define __USE_GNU -#include -#include -#include "pico_ipv4.h" -#include "pico_ipv6.h" -#include "pico_stack.h" -#include "pico_socket.h" -#include "pico_dev_vde.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -static __thread int in_the_stack = 0; -static int initialized = 0; -#define ptsock_dbg printf - - - - -#define swap_socketcall(call, name) \ -{ \ - const char *msg; \ - if (host_##call == NULL) { \ - *(void **)(&host_##call) = dlsym(RTLD_NEXT, name); \ - if ((msg = dlerror()) != NULL) \ - fprintf (stderr, "%s: dlsym(%s): %s\n", "picotcp", name, msg); \ - } \ -} - - -#define conditional_steal_call(call, i, ...) \ - if(in_the_stack) { \ - return host_##call(i, ## __VA_ARGS__); \ - } else { \ - if (get_pico_fd(i) > -1) { \ - int __pico_retval = pico_##call(get_pico_fd(i), ## __VA_ARGS__); \ - if (__pico_retval != 0) \ - errno = pico_err; \ - return __pico_retval; \ - }else { \ - return host_##call(i, ## __VA_ARGS__); \ - } \ - } - -static int max_fd = 0; -static int *pico_fds = NULL; - -static int remap_fd(int pico_fd) -{ - int new_fd = open("/dev/zero", O_RDONLY); - int old_max = max_fd; - int i; - if (new_fd < 0) { - abort(); - } - if (max_fd < new_fd + 1) - max_fd = new_fd + 1; - if (pico_fds == NULL) { - pico_fds = malloc(sizeof(int) * max_fd); - for (i = 0; i < max_fd; i++) - pico_fds[i] = -1; - pico_fds[new_fd] = pico_fd; - return new_fd; - } - pico_fds = realloc(pico_fds, sizeof(int) * max_fd); - for (i = old_max; i < max_fd; i++) - pico_fds[i] = -1; - pico_fds[new_fd] = pico_fd; - return new_fd; -} - -static int get_pico_fd(int j) -{ - if (j >= max_fd) - return -1; - return pico_fds[j]; -} - - -static int (*host_socket ) (int domain, int type, int protocol) = NULL; -static int (*host_bind ) (int sockfd, const struct sockaddr *addr, socklen_t addrlen); -static int (*host_connect ) (int sockfd, const struct sockaddr *addr, socklen_t addrlen); -static int (*host_accept ) (int sockfd, struct sockaddr *addr, socklen_t *addrlen); -static int (*host_listen ) (int sockfd, int backlog); -static ssize_t (*host_recvfrom) (int sockfd, void *buf, size_t len, int flags, struct sockaddr *addr, int *addrlen); -static ssize_t (*host_recv ) (int sockfd, void *buf, size_t len, int flags); -static ssize_t (*host_read ) (int sockfd, void *buf, size_t len); -static ssize_t (*host_sendto ) (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen); -static ssize_t (*host_send ) (int sockfd, void *buf, size_t len, int flags); -static ssize_t (*host_write ) (int sockfd, const void *buf, size_t len); -static int (*host_close ) (int sockfd); -static int (*host_shutdown) (int sockfd, int how); -static int (*host_setsockopt) (int sockfd, int level, int optname, const void *optval, socklen_t optlen); -static int (*host_getsockopt) (int sockfd, int level, int optname, void *optval, socklen_t *optlen); - - int getaddrinfo(const char *node, const char *service, - const struct addrinfo *hints, - struct addrinfo **res); - - void freeaddrinfo(struct addrinfo *res); - - -static int (*host_getaddrinfo) (const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); -static int (*host_freeaddrinfo) (struct addrinfo *res); -static int (*host_poll) (struct pollfd *pfd, nfds_t npfd, int timeout); -static int (*host_ppoll) (struct pollfd *pfd, nfds_t npfd, const struct timespec *timeout_ts, const sigset_t *sigmask); -static int (*host_select) (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); -static int (*host_pselect) (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, - const sigset_t *sigmask); - -int socket(int domain, int type, int protocol) -{ - int new_sd, posix_fd = -1; - ptsock_dbg ("Called Socket (pid=%d) in_the_stack=%d\n", getpid(), in_the_stack); - if (in_the_stack) - return host_socket(domain, type, protocol); - if ((domain != AF_INET) && (domain != AF_INET6)) { - return host_socket(domain, type, protocol); - } - new_sd = pico_newsocket(domain, type, protocol); - if (new_sd < 0) { - ptsock_dbg("socket() call failed.\n"); - abort(); - } - posix_fd = remap_fd(new_sd); - ptsock_dbg ("Socket stolen, sd=%d, fd = %d\n", new_sd, posix_fd); - return posix_fd; -} - -int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) -{ - conditional_steal_call(bind, sockfd, addr, addrlen); -} - -int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) -{ - conditional_steal_call(connect, sockfd, addr, addrlen); -} - -int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) -{ - if(in_the_stack) { - return host_accept(sockfd, addr, addrlen); - } else { - int posix_fd, new_sd, listen_sd = get_pico_fd(sockfd); - if (listen_sd < 0) { - return host_accept(sockfd, addr, addrlen); - } - - new_sd = pico_accept(listen_sd, addr, addrlen); - if (new_sd < 0) - return -1; - posix_fd = remap_fd(new_sd); - ptsock_dbg ("Socket accepted, sd=%d, fd = %d\n", new_sd, posix_fd); - return posix_fd; - } -} - -int listen(int sockfd, int backlog) -{ - conditional_steal_call(listen, sockfd, backlog); -} - -ssize_t recv(int sockfd, void *buf, size_t len, int flags) -{ - conditional_steal_call(recvfrom, sockfd, buf, len, flags, 0, 0); -} - -ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen) -{ - conditional_steal_call(recvfrom, sockfd, buf, len, flags, addr, addrlen); -} - -ssize_t read(int sockfd, void *buf, size_t len) -{ - conditional_steal_call(read, sockfd, buf, len); -} - -ssize_t send(int sockfd, const void *buf, size_t len, int flags) -{ - conditional_steal_call(sendto, sockfd, buf, len, flags, 0, 0); -} - -ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen) -{ - conditional_steal_call(sendto, sockfd, buf, len, flags, addr, addrlen); -} - -ssize_t write(int sockfd, const void *buf, size_t len) -{ - conditional_steal_call(write, sockfd, buf, len); -} - -int close(int sockfd) -{ - int pico_sd; - if (in_the_stack) - return host_close(sockfd); - pico_sd = get_pico_fd(sockfd); - if (pico_sd < 0) - return host_close(sockfd); - pico_close(pico_sd); - pico_fds[sockfd] = -1; - return 0; -} - -int shutdown(int sockfd, int how) -{ - int pico_sd; - if (in_the_stack) - return host_shutdown(sockfd, how); - pico_sd = get_pico_fd(sockfd); - if (pico_sd < 0) - return host_shutdown(sockfd, how); - - if (how != SHUT_WR) - pico_fds[sockfd] = -1; - pico_shutdown(pico_sd, how); - return 0; -} - -int setsockopt (int sockfd, int level, int optname, const void *optval, socklen_t optlen) -{ - conditional_steal_call(setsockopt, sockfd, level, optname, optval, optlen); -} - -int getsockopt (int sockfd, int level, int optname, void *optval, socklen_t *optlen) -{ - conditional_steal_call(getsockopt, sockfd, level, optname, optval, optlen); -} - -int poll(struct pollfd *pfd, nfds_t npfd, int timeout) -{ - if(in_the_stack) { - return host_poll(pfd, npfd, timeout); - } else { - int i, j = 0; - struct pollfd pico_pfd[npfd]; - for (i = 0; i < npfd; i++) { - pico_pfd[j].fd = get_pico_fd(pfd[i].fd); - if (pico_pfd[j].fd >= 0) { - j++; - pico_pfd[j].events = pfd[i].events; - } - } - if (j > 0) { - int pico_retval = pico_poll(pico_pfd, j, timeout); - if (pico_retval < 0) - errno = pico_err; - return pico_retval; - } else { - errno = EINVAL; - return -1; - } - } -} - - -int ppoll(struct pollfd *pfd, nfds_t npfd, const struct timespec *timeout_ts, const sigset_t *sigmask) -{ - if(in_the_stack) { - return host_ppoll(pfd, npfd, timeout_ts, sigmask); - } else { - int i, j = 0; - struct pollfd pico_pfd[npfd]; - for (i = 0; i < npfd; i++) { - pico_pfd[j].fd = get_pico_fd(pfd[i].fd); - if (pico_pfd[j].fd >= 0) { - j++; - pico_pfd[j].events = pfd[i].events; - } - } - if (j > 0) { - int pico_retval = pico_ppoll(pico_pfd, j, timeout_ts, NULL); - if (pico_retval < 0) - errno = pico_err; - return pico_retval; - } else { - errno = EINVAL; - return -1; - } - } -} - -int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask) -{ - pico_fd_set rs, ws, es; - int pico_retval = -1; - - PICO_FD_ZERO(&rs); - PICO_FD_ZERO(&ws); - PICO_FD_ZERO(&es); - - if(in_the_stack) { - return host_pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask); - } else { - int i, max = -1; - for (i = 0; i < nfds; i++) { - int picofd = get_pico_fd(i); - if (picofd >= 0) { - if (FD_ISSET(i, readfds)) - PICO_FD_SET(picofd, &rs); - if (FD_ISSET(i, writefds)) - PICO_FD_SET(picofd, &ws); - if (FD_ISSET(i, exceptfds)) - PICO_FD_SET(picofd, &es); - } - if (picofd > max) - max = picofd; - } - if (max < 0) { - errno = EINVAL; - return -1; - } - max++; - pico_retval = pico_pselect(max, &rs, &ws, &es, timeout, NULL); - if (pico_retval < 0) - errno = pico_err; - else { - for(i = 0; i < nfds; i++) { - int picofd = get_pico_fd(i); - FD_CLR(i, readfds); - FD_CLR(i, writefds); - FD_CLR(i, exceptfds); - if (picofd >= 0) { - if (FD_ISSET(picofd, &rs)) - FD_SET(i, readfds); - if (FD_ISSET(picofd, &ws)) - FD_SET(i, writefds); - if (FD_ISSET(picofd, &es)) - FD_SET(i, exceptfds); - } - } - } - return pico_retval; - } -} - -int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -{ - if(in_the_stack) { - return host_select(nfds, readfds, writefds, exceptfds, timeout); - } else { - if (timeout) { - const struct timespec ts = {timeout->tv_sec, timeout->tv_usec * 1000}; - return pselect(nfds, readfds, writefds, exceptfds, &ts, NULL); - } else { - return pselect(nfds, readfds, writefds, exceptfds, NULL, NULL); - } - } -} - -void *pico_tick_thread(void *arg) { - struct pico_ip4 addr, netmask, gateway, zero = {}; - struct pico_device *vde; - struct pico_ip4 v4_ip_host, v4_ip_route; - struct pico_ip4 v4_mask; - struct pico_ip4 v4_zero={}, v4_gateway; - struct pico_ip6 v6_public; - struct pico_ip6 v6_netmask = {0xff,0xff,}; - struct pico_device *tun; - in_the_stack = 1; - - pico_bsd_init(); - pico_stack_init(); - - tun = (struct pico_device *) pico_tun_create("psx0"); - if (!tun) - abort(); - - pico_string_to_ipv4("192.168.2.150",&v4_ip_host.addr); - pico_string_to_ipv4("192.168.2.1",&v4_ip_route.addr); - pico_string_to_ipv4("255.255.0.0",&v4_mask.addr); - pico_string_to_ipv4("192.168.2.1",&v4_gateway.addr); - pico_string_to_ipv6("7a55::150",v6_public.addr); - - pico_ipv4_link_add(tun, v4_ip_host, v4_mask); - pico_ipv4_route_add(v4_ip_route, v4_mask, v4_gateway, 1, NULL); - pico_ipv6_link_add(tun, v6_public, v6_netmask); - - for (;;) { - pico_bsd_stack_tick(); - usleep(1000); - } -} - - -int __attribute__((constructor)) pico_wrapper_start(void) -{ - pthread_t ticker; - if (initialized++) - return 0; - printf("Stealing all your system calls, please wait...\n"); - swap_socketcall(socket , "socket"); - swap_socketcall(bind , "bind"); - swap_socketcall(connect , "connect"); - swap_socketcall(accept , "accept"); - swap_socketcall(listen , "listen"); - swap_socketcall(recvfrom, "recvfrom"); - swap_socketcall(recv , "recv"); - swap_socketcall(read , "read"); - swap_socketcall(sendto , "sendto"); - swap_socketcall(send , "send"); - swap_socketcall(write , "write"); - swap_socketcall(close , "close"); - swap_socketcall(shutdown, "shutdown"); - swap_socketcall(setsockopt, "setsockopt"); - swap_socketcall(getaddrinfo, "getaddrinfo"); - swap_socketcall(freeaddrinfo, "freeaddrinfo"); - swap_socketcall(poll, "poll"); - swap_socketcall(ppoll, "ppoll"); - swap_socketcall(select, "select"); - swap_socketcall(pselect, "pselect"); - pthread_create(&ticker, NULL, pico_tick_thread, NULL); - sleep(1); - return 0; -} -