/*------------------------------------------- | Name:_system_exit | Description: | Parameters: | Return Type: | Comments: | See: ---------------------------------------------*/ void _system_exit(int status) { kernel_pthread_t* pthread_ptr= kernel_pthread_self(); pid_t pid = pthread_ptr->pid; exit_t exit_dt; #if ATEXIT_MAX>0 { atexit_func_t* p_atexit_func; while( *(p_atexit_func = process_lst[pid]->p_atexit_func++) ) { (*p_atexit_func)(); } } #endif //mutex stdio release if(pthread_ptr->stat&PTHREAD_STATUS_SIGHANDLER) { //to do lonjmp() will must use this method to release semaphore; //release semaphore stdio_sem (instead of use atexit()???;) #if !defined(__KERNEL_LOAD_LIB) kernel_pthread_mutex_destroy(&stdin->mutex); kernel_pthread_mutex_destroy(&stdout->mutex); kernel_pthread_mutex_destroy(&stderr->mutex); #endif } exit_dt.pid=pid; exit_dt.status = status; __mk_syscall(_SYSCALL_EXIT,exit_dt); //no return: thread is destroyed }
/** * \brief Start listening to the specified port. Standard BSD listen() with internal name. * \param[in] desc socket descriptor to start listening on. * \param[in] maxcon is be the maximum TCP connections to accept on that socket. Unsued parameter with current implementation. * \details To accept connections, a socket is first created with socket(), a willingness to accept incoming connections is specified with listen(), and then the connections are accepted with accept(). The listen() call applies only to sockets of type \ref SOCK_STREAM (TCP). * \note Default maximum number of connections unknown? * \return On connection success, zero is returned. On error, -1 is returned. * \callgraph */ int _sys_sock_listen(int fd,int maxcon){ #if defined (__KERNEL_NET_IPSTACK) && defined (USE_UIP_CORE) pid_t pid; kernel_pthread_t* pthread_ptr; hsock_t hsock = 0; desc_t desc; // // if(!(pthread_ptr = kernel_pthread_self())){ __set_kernel_pthread_errno(ESRCH); return -1; } if((pid=pthread_ptr->pid)<=0){ __set_kernel_pthread_errno(ESRCH); return -1; } // if(fd<0){ __set_kernel_pthread_errno (EBADF); return -1; } // desc = process_lst[pid]->desc_tbl[fd]; if(desc<0){ __set_kernel_pthread_errno (EBADF); return -1; } if(!ofile_lst[desc].used){ __set_kernel_pthread_errno (EBADF); return -1; } if(! (hsock = ofile_lst[desc].p) ){ __set_kernel_pthread_errno (ENOTSOCK); return -1; } if(((socket_t*)hsock)->protocol!=IPPROTO_TCP){ __set_kernel_pthread_errno (EPROTONOSUPPORT); return -1; } //lock __lock_io(ofile_lst[desc].owner_pthread_ptr_write,desc,O_WRONLY); __lock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); // ((socket_t*)hsock)->state = STATE_SOCKET_LISTEN; #if UIP_CONF_IPV6 uip_listen( (u16_t)( ((socket_t*)hsock)->addr_in.sin6_port) ); #else uip_listen( (u16_t)( ((socket_t*)hsock)->addr_in.sin_port) ); #endif //unlock __unlock_io(ofile_lst[desc].owner_pthread_ptr_write,desc,O_WRONLY); __unlock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); // __set_kernel_pthread_errno (0); // return 0; #else return -1; #endif } //end of _sys_sock_listen()
/* * Return current thread's timeout info */ struct sys_timeouts *sys_arch_timeouts(void) { struct lwip_thread *t; kernel_pthread_t* pthread; pthread = kernel_pthread_self(); //p_task = OS_GetpCurrentTask(); for(t = threads; t; t = t->next) if (&t->t == pthread) return &(t->to); to.next=(struct sys_timeout *)0; return &to; }
/*------------------------------------------- | Name:_slip_send_packet | Description: | Parameters: | Return Type: | Comments:sends a packet of length "len", starting at | location "p". | See: ---------------------------------------------*/ int _dev_slip_write_c(desc_t desc, const unsigned char c, int last){ int cb=-1; #ifdef USE_SLIP_WRITE_BUFFER if(!(ofile_lst[desc].oflag&O_NONBLOCK)) { desc_t slip_desc=ofile_lst[desc].desc_prv; slip_write_t* p_slip_write = &(((slip_io_t*)ofile_lst[slip_desc].p)->write); if(!p_slip_write) return -1; p_slip_write->buf[p_slip_write->cb++]=c; if(last) { cb = p_slip_write->cb; p_slip_write->cb = 0; if((cb = ofile_lst[desc].pfsop->fdev.fdev_write(desc,p_slip_write->buf,cb))<0) { return -1; } } } return 1; #else kernel_pthread_t* pthread_ptr; if(!(pthread_ptr = kernel_pthread_self())) return -1; if(!(ofile_lst[desc].oflag&O_NONBLOCK)) { if((cb = ofile_lst[desc].pfsop->fdev.fdev_write(desc,(void*)&c,1))<0) { return -1; } //see write() in devio.c. write wait an event from last character //fix a deadlock pb in this case. if(last) return cb; do { __wait_io_int(pthread_ptr); } while(ofile_lst[desc].pfsop->fdev.fdev_isset_write && ofile_lst[desc].pfsop->fdev.fdev_isset_write(desc)); } return cb; #endif }
/** * \brief Closes a socket. Standard BSD shutdown() with internal name. * \param[in] desc socket descriptor to close. * \param[in] how Shutdown method : \ref SHUT_RD, \ref SHUT_WR or \ref SHUT_RDWR. * \note Similar to "close()" BSD function when using \ref SHUT_RDWR method (no need to call close()). * \note Only \ref SHUT_RDWR is supported with current implementation. * \return shutdown() returns 0 on success and -1 on failure. * \callgraph */ int _sys_sock_shutdown(int fd, int how){ #if defined (__KERNEL_NET_IPSTACK) && defined (USE_UIP_CORE) kernel_pthread_t* pthread_ptr; // if(!(pthread_ptr = kernel_pthread_self())){ __set_kernel_pthread_errno(ESRCH); return -1; } // if(how != SHUT_RDWR){ __set_kernel_pthread_errno (EOPNOTSUPP); return -1; //only SHUT_RDWR is supported with current implementation } // return(_sys_sock_close(fd)); #else return -1; #endif } //end of _sys_sock_shutdown()
/*-------------------------------------------- | Name: kernel_sigqueue_wait | Description: | Parameters: none | Return Type: none | Comments: | See: ----------------------------------------------*/ int kernel_sigqueue_wait(struct kernel_sigevent_st* kernel_sigevent){ struct kernel_sigqueue_st* p= &kernel_pthread_self()->kernel_sigqueue; if(!p) return -1; //wait event if(kernel_sem_wait(&p->kernel_sem->object.kernel_object_sem.kernel_sem)<0) return -1; //extract sigevent in queue if(kernel_sigevent->si_code==SI_SYSTEM) { //filter event on SI_SYSTEM if(kernel_sigqueue_sysextract(p,kernel_sigevent)<0) return -1; }else{ if(kernel_sigqueue_extract(p,kernel_sigevent)<0) return -1; } return 0; }
/*------------------------------------------- | Name:_slip_send_packet | Description: | Parameters: | Return Type: | Comments:sends a packet of length "len", starting at | location "p". | See: ---------------------------------------------*/ int _dev_slip_read_c(desc_t desc, unsigned char* c,int first){ int cb=-1; kernel_pthread_t* pthread_ptr; if(!(pthread_ptr = kernel_pthread_self())) return -1; #ifdef USE_SLIP_READ_BUFFER if(!(ofile_lst[desc].oflag&O_NONBLOCK)) { desc_t slip_desc=ofile_lst[desc].desc_prv; slip_read_t* p_slip_read = &(((slip_io_t*)ofile_lst[slip_desc].p)->read); if(!p_slip_read) return -1; if(p_slip_read->cb>0 && p_slip_read->i<p_slip_read->cb) { *c=p_slip_read->buf[p_slip_read->i++]; return 1; } p_slip_read->i=0; while(ofile_lst[desc].pfsop->fdev.fdev_isset_read && ofile_lst[desc].pfsop->fdev.fdev_isset_read(desc)) __wait_io_int(pthread_ptr); //wait incomming data if((p_slip_read->cb= ofile_lst[desc].pfsop->fdev.fdev_read(desc,p_slip_read->buf,SLIP_READ_BUFFER_SZ))<=0) return p_slip_read->cb; *c=p_slip_read->buf[p_slip_read->i++]; } return 1; #else if(!(ofile_lst[desc].oflag&O_NONBLOCK)) { if(!first) { while(ofile_lst[desc].pfsop->fdev.fdev_isset_read && ofile_lst[desc].pfsop->fdev.fdev_isset_read(desc)) __wait_io_int(pthread_ptr); //wait incomming data } cb=ofile_lst[desc].pfsop->fdev.fdev_read(desc,c,1); } return cb; #endif }
/*-------------------------------------------- | Name: kernel_sigqueue_timedwait | Description: | Parameters: none | Return Type: none | Comments: | See: ----------------------------------------------*/ int kernel_sigqueue_timedwait(struct kernel_sigevent_st* kernel_sigevent,int flag,const struct timespec * abs_timeout){ struct kernel_sigqueue_st* p= &kernel_pthread_self()->kernel_sigqueue; if(!p) return -1; //wait event until timeout or event signaled if(kernel_sem_timedwait(&p->kernel_sem->object.kernel_object_sem.kernel_sem,flag,abs_timeout)<0) return -1; //extract sigevent in queue if(kernel_sigevent->si_code==SI_SYSTEM) { //filter event on SI_SYSTEM if(kernel_sigqueue_sysextract(p,kernel_sigevent)<0) return -1; }else{ if(kernel_sigqueue_extract(p,kernel_sigevent)<0) return -1; } return 0; }
/*-------------------------------------------- | Name: dev_mem_read | Description: | Parameters: none | Return Type: none | Comments: | See: ----------------------------------------------*/ int dev_mem_read(desc_t desc,char* buf, int size){ int i=0; int j=-1; int data_offset; int ret=-1; kernel_pthread_t* pthread_ptr; if(!(pthread_ptr = kernel_pthread_self())) return -1; for(i=0; i<=MAX_MEM_ADDR; i++) { //nothing change for the current offset? if(i==MAX_MEM_ADDR) { // not register listener make simple copy of current address if(j>=0) { i=j; goto label_dev_mem_read_copy; } //nothing change at current offset if((ofile_lst[desc].oflag&O_NONBLOCK) || !ret) return ret; //if !ret change detected on this descripteur but not at the current offset //no change detected for on any address for this desc __wait_io_int(pthread_ptr); //blocking call //restart find change i=0; } //get address index for current offset if( (ofile_lst[desc].offset>=addr_list[i].addr) && (ofile_lst[desc].offset < (addr_list[i].addr+addr_list[i].len)) ) j=i; // if(addr_list[i].vector_listener&(0x00000001<<desc)) //is it register listener j=-1; //yes //change? if( (addr_list[i].vector_isset_read&(0x00000001<<desc)) ) { ret=0; ////something change yes //lseek() change at the current offset if( (ofile_lst[desc].offset<addr_list[i].addr) || (ofile_lst[desc].offset >= (addr_list[i].addr+addr_list[i].len)) ) continue; //continue to try find change at the current offset //something change at the current offset go to read the address and copy in the buf }else{ //continue to find change continue; } //yes, now read the address and copy in the buf //pthread_clear_event(&ofile_lst[desc].pthread_owner); label_dev_mem_read_copy: //lock __dev_mem_lock(); //check real address if(!addr_list[i].pdata) { __dev_mem_unlock(); return -1; } // if(buf) addr_list[i].vector_isset_read&=~(0x00000001<<desc); data_offset= ofile_lst[desc].offset-addr_list[i].addr; if(size>(addr_list[i].len-data_offset)) size = addr_list[i].len-data_offset; //WARNING TO DO //check new size<old size. risk of buffer overflow if(buf) memcpy(buf,(char*)addr_list[i].pdata+data_offset,size); else size=-size; ofile_lst[desc].offset+=size; //unlock __dev_mem_unlock(); return size; } return ret; }
/** * \brief Closes a socket. Standard BSD close() with internal name. * \param[in] desc socket descriptor to close. * \return close() returns 0 on success and -1 on failure. * \callgraph */ int _sys_sock_close(int fd){ #if defined (__KERNEL_NET_IPSTACK) && defined (USE_UIP_CORE) pid_t pid; kernel_pthread_t* pthread_ptr; hsock_t hsock = 0; desc_t desc; int r; // if(!(pthread_ptr = kernel_pthread_self())){ __set_kernel_pthread_errno(ESRCH); return -1; } if((pid=pthread_ptr->pid)<=0){ __set_kernel_pthread_errno(ESRCH); return -1; } // if(fd<0){ __set_kernel_pthread_errno (EBADF); return -1; } // desc = process_lst[pid]->desc_tbl[fd]; if(desc<0){ __set_kernel_pthread_errno (EBADF); return -1; } if(!ofile_lst[desc].used){ __set_kernel_pthread_errno (EBADF); return -1; } if(! (hsock = ofile_lst[desc].p) ){ __set_kernel_pthread_errno (ENOTSOCK); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_CLOSED){ __set_kernel_pthread_errno (ENOTCONN); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_ABORTED){ __set_kernel_pthread_errno (ECONNABORTED); return -1; } // if( ((socket_t*)hsock)->socksconn!=NULL){ /* while( ((socket_t*)hsock)->w != ((socket_t*)hsock)->socksconn->_r ) __WAIT_SOCKET_EVENT(hsock); */ } // if( ((socket_t*)(hsock))->state == STATE_SOCKET_CLOSED || ((socket_t*)(hsock))->state == STATE_SOCKET_ABORTED || ((socket_t*)(hsock))->state == STATE_SOCKET_ACCEPTED){ __CLR_SOCKET_EVENT(hsock); close(fd); return -1; } // ((socket_t*)(hsock))->state=STATE_SOCKET_CLOSE; // while( ((socket_t*)(hsock))->state==STATE_SOCKET_WAIT ) __WAIT_SOCKET_EVENT(pthread_ptr,hsock); // if(!ofile_lst[desc].used){ __set_kernel_pthread_errno (EINVAL); return -1; } if(! (hsock = ofile_lst[desc].p) ){ __set_kernel_pthread_errno (ENOTSOCK); return -1; } // __CLR_SOCKET_EVENT(hsock); // if(((socket_t*)hsock)->protocol==IPPROTO_UDP){ //free udp connection ((socket_t*)hsock)->uip_udp_conn->lport = 0; } // r=close(fd); // if(!r) __set_kernel_pthread_errno(0); // return r; #else return -1; #endif } //end of '_sys_sock_close'
/** * \brief Sends a packet to a remote host. Standard BSD sendto() with internal name. * \param[in] desc socket descriptor created with socket() * \param[in] buf buffer with payload to send * \param[in] length length in bytes of the \p buf buffer * \param[in] flags is formed by OR'ing options. No options are supported with current implementation. * \param[in] dest_addr to destination address and port. * \param[in] dest_len should be the length of \p dest_addr structure. Unused parameter with current implementation. * \details Writes data to the remote host specified by \p dest_addr into \p buf. The socket must be a \ref SOCK_DGRAM (UDP) socket. \p length should be the amount of data in the buffer. * \return sendto() returns the amount of data which was written. If there is an error, -1 is returned. * \callgraph */ int _sys_sock_sendto(int fd, const void *buf, int length, int flags, const struct sockaddr *dest_addr,socklen_t dest_len){ #if defined (__KERNEL_NET_IPSTACK) && defined (USE_UIP_CORE) pid_t pid; kernel_pthread_t* pthread_ptr; hsock_t hsock = 0; desc_t desc; #if UIP_CONF_IPV6 desc_t desc_if; #endif int r; // if(!(pthread_ptr = kernel_pthread_self())){ __set_kernel_pthread_errno(ESRCH); return -1; } if((pid=pthread_ptr->pid)<=0){ __set_kernel_pthread_errno(ESRCH); return -1; } // if(fd<0){ __set_kernel_pthread_errno (EBADF); return -1; } // desc = process_lst[pid]->desc_tbl[fd]; if(desc<0){ __set_kernel_pthread_errno (EBADF); return -1; } if(!ofile_lst[desc].used){ __set_kernel_pthread_errno (EBADF); return -1; } if(! (hsock = ofile_lst[desc].p) ){ __set_kernel_pthread_errno (ENOTSOCK); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_CLOSED){ __set_kernel_pthread_errno (ENOTCONN); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_ABORTED){ __set_kernel_pthread_errno (ECONNABORTED); return -1; } if(((socket_t*)hsock)->protocol!=IPPROTO_UDP){ __set_kernel_pthread_errno (EPROTONOSUPPORT); return -1; } // #if UIP_CONF_IPV6 desc_if = uip_core_if_indextodesc(((socket_t*)hsock)->addr_in.sin6_scope_id,O_RDONLY); if(desc_if<0){ __set_kernel_pthread_errno (EINVAL); return -1; } #endif /*to do if(dev_core_ioctl(desc_if,NETUP)<0){ __set_kernel_pthread_errno (ENETDOWN); return -1; } */ //lock __lock_io(ofile_lst[desc].owner_pthread_ptr_write,desc,O_WRONLY); // #if UIP_CONF_IPV6 memcpy(&((socket_t*)hsock)->addr_in_to,dest_addr,sizeof(struct _sockaddr_in6)); #else memcpy(&((socket_t*)(hsock))->addr_in_to,dest_addr,sizeof(struct _sockaddr_in)); #endif //unlock __unlock_io(ofile_lst[desc].owner_pthread_ptr_write,desc,O_WRONLY); // r=write(fd,(void*)buf,length); if(r<0){ if( ((socket_t*)(hsock))->state==STATE_SOCKET_CLOSED){ __set_kernel_pthread_errno (ENOTCONN); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_ABORTED){ __set_kernel_pthread_errno (ECONNABORTED); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_NETDOWN){ __set_kernel_pthread_errno (ENETDOWN); return -1; } // /*UIP_EVENT(EVT_UIP_SOCK + EVT_LVL_ERR + EVT_UIP_SOCK_SENDTO_FAIL, desc, &length, sizeof(length), "sendto() failure (return %d)(flags %d)", r, flags);*/ }else{ __set_kernel_pthread_errno(0); } return r; #else return -1; #endif } //end of _sys_sock_sendto()
/** * \brief Receives a packet on a openned socket. Standard BSD recvfrom() with internal name. * \param[in] desc socket descriptor created with socket() * \param[out] buf buffer to copy received data * \param[in] length length in bytes of the \p buf buffer * \param[in] flags is formed by OR'ing options. \ref MSG_DONTWAIT and \ref MSG_PEEK supported in current implementation. * \param[out] address to get the source address of the received packet * \param[out] address_len is unused parameter with current implementation * \details Reads data from the remote host specified by \p address into \p buf. The socket must be a \ref SOCK_DGRAM (UDP) socket. \p length should be the size of the buffer.\n recvfrom() may not fill the entire buffer.\n\n \ref MSG_DONTWAIT This flag enables non-blocking operation (recvfrom() will not block waiting for data).\n \ref MSG_PEEK This flag causes the receive operation to return data from the beginning of the receive queue without removing that data from the queue. Thus, a subsequent receive call will return the same data.\n In case of multiple sources received on the same socket the \p address parameter will contain the source of the actual dequeued packet (the one in \p buf buffer). * \return recvfrom() returns the amount of data which was read. Even with \ref MSG_PEEK flag, only actual amount of data read is returned which may be smaller than packet size (maxed to \p length parameter value). If there is an error, -1 is returned. * \callgraph */ int _sys_sock_recvfrom(int fd, void *buf, int length, int flags, struct sockaddr *address,socklen_t* address_len){ #if defined (__KERNEL_NET_IPSTACK) && defined (USE_UIP_CORE) pid_t pid; kernel_pthread_t* pthread_ptr; hsock_t hsock = 0; desc_t desc; #if UIP_CONF_IPV6 desc_t desc_if; #endif int r; // if(!(pthread_ptr = kernel_pthread_self())){ __set_kernel_pthread_errno(ESRCH); return -1; } if((pid=pthread_ptr->pid)<=0){ __set_kernel_pthread_errno(ESRCH); return -1; } // if(fd<0){ __set_kernel_pthread_errno (EBADF); return -1; } // desc = process_lst[pid]->desc_tbl[fd]; if(desc<0){ __set_kernel_pthread_errno (EBADF); return -1; } // if(!ofile_lst[desc].used){ __set_kernel_pthread_errno (EBADF); return -1; } if(! (hsock = ofile_lst[desc].p) ){ __set_kernel_pthread_errno (ENOTSOCK); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_CLOSED){ __set_kernel_pthread_errno (ENOTCONN); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_ABORTED){ __set_kernel_pthread_errno (ECONNABORTED); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_NETDOWN){ __set_kernel_pthread_errno (ENETDOWN); return -1; } if(((socket_t*)hsock)->protocol!=IPPROTO_UDP){ __set_kernel_pthread_errno (EPROTONOSUPPORT); return -1; } // #if UIP_CONF_IPV6 desc_if = uip_core_if_indextodesc(((socket_t*)hsock)->addr_in.sin6_scope_id,O_RDONLY); if(desc_if<0){ __set_kernel_pthread_errno (EINVAL); return -1; } #endif /* to do if(dev_core_ioctl(desc_if,NETUP)<0){ __set_kernel_pthread_errno (ENETDOWN); return -1; } */ //lock __lock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); //Prepare flags if(flags & MSG_DONTWAIT) ofile_lst[desc].oflag |= O_NONBLOCK; //GD 2011/05/24 //GD 2011/07/05: standard MSG_DONTWAIT flag compliancy (but still a workaround to pass the flag to dev_core_read()) if(flags & MSG_PEEK) ((socket_t*)hsock)->flags |= MSG_PEEK; //unlock __unlock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); // if( r=read(fd,buf,length) ) { // #if UIP_CONF_IPV6 memcpy(address,&((socket_t*)hsock)->addr_in_from,sizeof(struct _sockaddr_in6)); #else memcpy( address,&((socket_t*)(hsock))->addr_in_from,sizeof(struct _sockaddr_in)); #endif } if(r<0){ if( ((socket_t*)(hsock))->state==STATE_SOCKET_CLOSED){ __set_kernel_pthread_errno (ENOTCONN); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_ABORTED){ __set_kernel_pthread_errno (ECONNABORTED); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_NETDOWN){ __set_kernel_pthread_errno (ENETDOWN); return -1; } // /*UIP_EVENT(EVT_UIP_SOCK + EVT_LVL_ERR + EVT_UIP_SOCK_RECVFROM_FAIL, desc, &flags, sizeof(flags), "recvfrom() failure (return %d)", r);*/ }else{ __set_kernel_pthread_errno(0); } //Enter Semaphore //lock __lock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); //Restore flags if(flags & MSG_DONTWAIT) ofile_lst[desc].oflag &= ~(O_NONBLOCK); if(flags & MSG_PEEK) ((socket_t*)hsock)->flags &= ~(MSG_PEEK); //unlock __unlock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); // return r; #else return -1; #endif } // end of _sys_sock_recvfrom()
/*-------------------------------------------- | Name: _system_alloca | Description: | Parameters: none | Return Type: none | Comments: | See: ----------------------------------------------*/ void* _system_alloca(size_t size) { kernel_pthread_t* pthread_ptr= kernel_pthread_self(); return kernel_pthread_alloca(pthread_ptr,size); }
/** * \brief Connects a socket to a remote host on a given address and port. Standard BSD connect() with internal name. * \param[in] desc socket descriptor created with socket() * \param[in] address must contain the address and port of the remote host. Must be in IPv6 format with current implementation. * \param[in] len is the length of \p address structure. (Unused parameter with current implementation. Assumes IPv6 structures length.) * \details connect() must be used in a TCP \b client application. The function call blocks until the connection is established. * \return On connection success, zero is returned. On error, -1 is returned. * \callgraph */ int _sys_sock_connect(int fd, struct _sockaddr *address,int len){ #if defined (__KERNEL_NET_IPSTACK) && defined (USE_UIP_CORE) pid_t pid; kernel_pthread_t* pthread_ptr; struct uip_conn * uip_conn; desc_t desc; hsock_t hsock = 0; if(!(pthread_ptr = kernel_pthread_self())){ __set_kernel_pthread_errno(ESRCH); return -1; } if((pid=pthread_ptr->pid)<=0){ __set_kernel_pthread_errno(ESRCH); return -1; } // if(fd<0){ __set_kernel_pthread_errno (EBADF); return -1; } // desc = process_lst[pid]->desc_tbl[fd]; if(desc<0){ __set_kernel_pthread_errno (EBADF); return -1; } if(!ofile_lst[desc].used){ __set_kernel_pthread_errno (EBADF); return -1; } if(! (hsock = ofile_lst[desc].p) ){ __set_kernel_pthread_errno (ENOTSOCK); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_CLOSED){ __set_kernel_pthread_errno (ENOTCONN); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_ABORTED){ __set_kernel_pthread_errno (ECONNABORTED); return -1; } if(((socket_t*)hsock)->protocol!=IPPROTO_TCP){ __set_kernel_pthread_errno (EPROTONOSUPPORT); return -1; } //lock __lock_io(ofile_lst[desc].owner_pthread_ptr_write,desc,O_WRONLY); __lock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); // ((socket_t*)hsock)->state = STATE_SOCKET_CONNECT; // #if UIP_CONF_IPV6 memcpy(&((socket_t*)hsock)->addr_in,address,sizeof(struct _sockaddr_in6)); // uip_conn = uip_connect((uip_ipaddr_t*)(&((socket_t*)hsock)->addr_in.sin6_addr.s6_addr), (u16_t)( ((socket_t*)hsock)->addr_in.sin6_port)); #else ((socket_t*)hsock)->addr_in.sin_port = ((struct _sockaddr_in*)address)->sin_port; ((socket_t*)hsock)->addr_in.sin_addr.s_addr = ((struct _sockaddr_in*)address)->sin_addr.s_addr; // uip_conn = uip_connect((uip_ipaddr_t*)(&((socket_t*)hsock)->addr_in.sin_addr.s_addr), (u16_t)( ((socket_t*)hsock)->addr_in.sin_port)); #endif // if(!uip_conn){ //unlock __unlock_io(ofile_lst[desc].owner_pthread_ptr_write,desc,O_WRONLY); __unlock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); return -1; } // ((socket_t*)hsock)->r =0; ((socket_t*)hsock)->w =0; // ((socket_t*)hsock)->socksconn = (struct socksconn_state *)(uip_conn->appstate.state); // ((socket_t*)hsock)->socksconn->__r = 0; ((socket_t*)hsock)->socksconn->_r = 0; ((socket_t*)hsock)->socksconn->_w = 0; // ((socket_t*)hsock)->socksconn->hsocks = hsock; //unlock __unlock_io(ofile_lst[desc].owner_pthread_ptr_write,desc,O_WRONLY); __unlock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); //to do:lepton //Wake ip_stack???? //to do:lepton: syscall kernel //OS_WakeTask(_OS_TASK_TCB(os_ipStack)); //Wait uip_connected(); uip_core_queue_put(UIP_POLL_REQUEST,desc,(void*)address,len); // __WAIT_SOCKET_EVENT(pthread_ptr,hsock); if(((socket_t*)hsock)->state != STATE_SOCKET_WAIT) return -1; // __set_kernel_pthread_errno (0); // return 0; #else return -1; #endif } //end of _sys_sock_connect()
/** * \brief Binds a socket to a local port and IP address. Standard BSD bind() with internal name. * \param[in] desc socket descriptor created with socket() * \param[in] address must contain the address and port for the socket to bind to. Must be in IPv6 format with current implementation. Address to zero means port will be openned on every interfaces. * \param[in] len is the length of \p address structure. (Unused parameter with current implementation. Assumes IPv6 structures length.) * \details bin() must be used in a \b server application that waits for incomming connection/packets. * \return On success, zero is returned. On error, -1 is returned. * \callgraph */ int _sys_sock_bind(int fd, struct _sockaddr *address,int len){ #if defined (__KERNEL_NET_IPSTACK) && defined (USE_UIP_CORE) pid_t pid; kernel_pthread_t* pthread_ptr; hsock_t hsock = 0; #if UIP_CONF_IPV6 desc_t desc_if; #endif desc_t desc; // // if(!(pthread_ptr = kernel_pthread_self())){ __set_kernel_pthread_errno(ESRCH); return -1; } if((pid=pthread_ptr->pid)<=0){ __set_kernel_pthread_errno(ESRCH); return -1; } // if(fd<0){ __set_kernel_pthread_errno (EBADF); return -1; } // desc = process_lst[pid]->desc_tbl[fd]; if(desc<0){ __set_kernel_pthread_errno (EBADF); return -1; } if(!ofile_lst[desc].used){ __set_kernel_pthread_errno (EBADF); return -1; } if(! (hsock = ofile_lst[desc].p) ){ __set_kernel_pthread_errno (ENOTSOCK); return -1; } //lock __lock_io(ofile_lst[desc].owner_pthread_ptr_write,desc,O_WRONLY); __lock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); // #if UIP_CONF_IPV6 ((socket_t*)hsock)->addr_in.sin6_port = ((struct _sockaddr_in6*)address)->sin6_port; //interface index in list (see uip_core interface list) if( ((struct _sockaddr_in6*)address)->sin6_scope_id>=IF_LIST_MAX){ //unlock __set_kernel_pthread_errno (EINVAL); //unlock __unlock_io(ofile_lst[desc].owner_pthread_ptr_write,desc,O_WRONLY); __unlock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); return -1; } // ((socket_t*)hsock)->addr_in.sin6_scope_id=((struct _sockaddr_in6*)address)->sin6_scope_id; // desc_if = uip_core_if_indextodesc(((socket_t*)hsock)->addr_in.sin6_scope_id,O_RDONLY); if(desc_if<0){ __set_kernel_pthread_errno (EINVAL); //unlock __unlock_io(ofile_lst[desc].owner_pthread_ptr_write,desc,O_WRONLY); __unlock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); return -1; } /* to do if(dev_core_ioctl(desc_if,NETUP)<0){ __set_kernel_pthread_errno (ENETDOWN); //unlock __unlock_io(ofile_lst[desc].owner_pthread_ptr_write,desc,O_WRONLY); __unlock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); return -1; } */ #else ((socket_t*)hsock)->addr_in.sin_port = ((struct _sockaddr_in*)address)->sin_port; #endif // if(((socket_t*)hsock)->protocol==IPPROTO_UDP){ ((socket_t*)hsock)->uip_udp_conn->rport = 0;//to do: check that uip_udp_bind(((socket_t*)hsock)->uip_udp_conn,((struct _sockaddr_in*)address)->sin_port); } // //unlock __unlock_io(ofile_lst[desc].owner_pthread_ptr_write,desc,O_WRONLY); __unlock_io(ofile_lst[desc].owner_pthread_ptr_read,desc,O_RDONLY); // __set_kernel_pthread_errno (0); // return 0; #else return -1; #endif } //end of _sys_sock_bind()
/** * \brief Creates a socket. Standard BSD socket() with internal name. * \param[in] af ("familly" or "domain") should only be \ref AF_INET6 (IPv4 support has been disabled so no AF_INET support). Parameter is ignore in current implementation, AF_INET6 is forced. * \param[in] type can be SOCK_STREAM for TCP sockets or SOCK_DGRAM for UDP sockets. * \param[in] protocol can be IPPROTO_TCP with \ref SOCK_STREAM type or IPPROTO_UDP with \ref SOCK_DGRAM with * \details UDP Example \code int desc = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); \endcode \n TCP Example \code int desc = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); \endcode * \return socket() returns a socket file descriptor (\ref desc_t) which is a small non-negative integer. This file descriptor number should be used for all other socket operations on that socket. If socket() encounters an error, it will return -1. * \callgraph */ int _sys_sock_socket(int af,int type,int protocol){ #if defined (__KERNEL_NET_IPSTACK) && defined (USE_UIP_CORE) pid_t pid; kernel_pthread_t* pthread_ptr; int fd; desc_t desc = INVALID_DESC; int _protocol; hsock_t hsock = 0; // if(protocol==IPPROTO_TCP){ _protocol = IPPROTO_TCP; }else if(protocol==IPPROTO_UDP){ _protocol = IPPROTO_UDP; }else if(!protocol && type==SOCK_STREAM){ _protocol = IPPROTO_TCP; }else if(!protocol && type==SOCK_DGRAM){ _protocol = IPPROTO_UDP; }else{ __set_kernel_pthread_errno(EPROTONOSUPPORT); return -1; } // if((fd = open("/dev/sock",O_RDWR,0))<0) return -1; // if(!(pthread_ptr = kernel_pthread_self())){ __set_kernel_pthread_errno(ESRCH); return -1; } if((pid=pthread_ptr->pid)<=0){ __set_kernel_pthread_errno(ESRCH); return -1; } // desc = process_lst[pid]->desc_tbl[fd]; if(desc<0) return -1; // _vfs_ioctl(desc,SETUIPSOCKOPT,_protocol); // if(! (hsock = ofile_lst[desc].p) ){ __set_kernel_pthread_errno (ENOTSOCK); return -1; } // if(((socket_t*)hsock)->protocol==IPPROTO_TCP) return fd; // ((socket_t*)hsock)->r =0; ((socket_t*)hsock)->w =0; // ((socket_t*)hsock)->state = STATE_SOCKET_OPENED; // ((socket_t*)hsock)->uip_udp_conn = uip_udp_new((void*)0,0); // if( !((socket_t*)hsock)->uip_udp_conn ){ close(desc); return -1; } // ((socket_t*)hsock)->socksconn = (struct socksconn_state *)(((socket_t*)hsock)->uip_udp_conn->appstate.state); // ((socket_t*)hsock)->socksconn->__r = 0; ((socket_t*)hsock)->socksconn->_r = 0; ((socket_t*)hsock)->socksconn->_w = 0; // ((socket_t*)hsock)->socksconn->hsocks = hsock; // ((socket_t*)hsock)->state = STATE_SOCKET_WAIT; // __set_kernel_pthread_errno (0); // return fd; #else return -1; #endif } //end of _sys_sock_socket()
/*------------------------------------------- | Name:select | Description: | Parameters: | Return Type: | Comments: | See: ---------------------------------------------*/ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout){ char b; char count=0; char wait=0; ldiv_t lr; pid_t pid; kernel_pthread_t* pthread_ptr; fd_set rfds=0; fd_set wfds=0; fd_set efds=0; fd_set unlock_rfds; fd_set unlock_wfds; fd_set unlock_efds; if(!(pthread_ptr = kernel_pthread_self())) return -1; if((pid= pthread_ptr->pid)<1) return -1; // rfds = readfds ? *readfds : 0; wfds = writefds ? *writefds : 0; efds = errorfds ? *errorfds : 0; //default timeout lr.quot = 10; //10 ms; //check and lock internal file descriptor for(b=0; b<sizeof(fd_set)|| b<nfds; b++) { desc_t desc; //check if((desc = process_lst[pid]->desc_tbl[b])<0 ) continue; /* if(!(ofile_lst[desc].oflag&O_NONBLOCK)) continue; */ //read if( ((rfds>>b) & 0x0001) ) { pthread_ptr->io_desc = desc; if(_trylock_io(pthread_ptr,ofile_lst[desc].desc,O_RDONLY)!=EBUSY) { //__atomic_in(); { desc_t _desc=ofile_lst[desc].desc; // if(ofile_lst[_desc].owner_pthread_ptr_read!=pthread_ptr) { do { //check if(ofile_lst[_desc].used<=0) { __unlock_io(pthread_ptr,ofile_lst[desc].desc,O_RDONLY); return -1; //error, stream not coherent :( } // //begin of section: protection from io interrupt __disable_interrupt_section_in(); // ofile_lst[_desc].owner_pthread_ptr_read=pthread_ptr; ofile_lst[_desc].owner_pid=pid; //end of section: protection from io interrupt __disable_interrupt_section_out(); // //aware: continue operation on original desc (see fattach() and _vfs_open() note 1) } while((_desc=ofile_lst[_desc].desc_nxt[0])>=0); } } //__atomic_out(); }else if (readfds) { *readfds=(*readfds&(~(0x01<<b))); } continue; } //write if( ((wfds>>b) & 0x0001) ) { pthread_ptr->io_desc = desc; if(_trylock_io(pthread_ptr,desc,O_WRONLY)!=EBUSY) { __atomic_in(); { desc_t _desc=ofile_lst[desc].desc; // if(ofile_lst[_desc].owner_pthread_ptr_write!=pthread_ptr) { do { //check if(ofile_lst[_desc].used<=0) { __atomic_out(); __unlock_io(pthread_ptr,ofile_lst[desc].desc,O_WRONLY); return -1; //error, stream not coherent :( } // //begin of section: protection from io interrupt __disable_interrupt_section_in(); // ofile_lst[_desc].owner_pthread_ptr_write=pthread_ptr; ofile_lst[_desc].owner_pid=pid; //end of section: protection from io interrupt __disable_interrupt_section_out(); // //aware: continue operation on original desc (see fattach() and _vfs_open() note 1) } while((_desc=ofile_lst[_desc].desc_nxt[1])>=0); } } __atomic_out(); }else if(writefds) { *writefds=(*writefds&(~(0x01<<b))); } continue; } //exception if( ((efds>>b) & 0x0001) ) { pthread_ptr->io_desc = desc; if(_trylock_io(pthread_ptr,desc,O_WRONLY)!=EBUSY) { //begin of section: protection from io interrupt __disable_interrupt_section_in(); // ofile_lst[desc].owner_pid=pid; ofile_lst[desc].owner_pthread_ptr_write = pthread_ptr; //end of section: protection from io interrupt __disable_interrupt_section_out(); // }else{ *errorfds=(*errorfds&(~(0x01<<b))); } continue; } } //set file descriptor vector rfds = readfds ? *readfds : 0; wfds = writefds ? *writefds : 0; efds = errorfds ? *errorfds : 0; if(readfds) memset(readfds,0,sizeof(fd_set)); if(writefds) memset(writefds,0,sizeof(fd_set)); if(errorfds) memset(errorfds,0,sizeof(fd_set)); //set unlock file descriptor vector unlock_rfds=rfds; unlock_wfds=wfds; unlock_efds=efds; start: for(b=0; b<sizeof(fd_set)|| b<nfds; b++) { desc_t desc; int isset=0; //check if((desc = process_lst[pid]->desc_tbl[b])<0 ) continue; /* if(!(ofile_lst[desc].oflag&O_NONBLOCK)) continue; */ //read if( ((rfds>>b) & 0x0001) ) { if(!ofile_lst[desc].pfsop->fdev.fdev_isset_read(desc)) { isset=1; if(readfds) *readfds=(*readfds|((0x01<<b))); }else if(readfds) { *readfds=(*readfds&(~(0x01<<b))); } //continue; } //write if( ((wfds>>b) & 0x0001) ) { if(!ofile_lst[desc].pfsop->fdev.fdev_isset_write(desc)) { isset=1; if(writefds) *writefds=(*writefds|((0x01<<b))); }else if(writefds) { *writefds=(*writefds&(~(0x01<<b))); } //continue; } //exception if( ((efds>>b) & 0x0001) ) { //to do: select on exception //continue; } if(isset) count++; } //wait if(!count && !wait) { struct timespec abs_timeout; // if(timeout) { abs_timeout.tv_sec = timeout->tv_sec; abs_timeout.tv_nsec = timeout->tv_usec*1000; __wait_io_int2(pthread_ptr,&abs_timeout); }else{ /* abs_timeout.tv_sec = 0; abs_timeout.tv_nsec = 0; */ __wait_io_int2(pthread_ptr,NULL); } // // wait=1; goto start; } //unlock internal file descriptor for(b=0; b<sizeof(fd_set)|| b<nfds; b++) { desc_t desc; int isset=0; //check if((desc = process_lst[pid]->desc_tbl[b])<0 ) continue; /* if(!(ofile_lst[desc].oflag&O_NONBLOCK)) continue; */ //unlock descriptor if( ((unlock_rfds>>b) & 0x0001) ) { __unlock_io(pthread_ptr,ofile_lst[desc].desc,O_RDONLY); //yes isset=1 or wait =1 then select is terminated } if( ((unlock_wfds>>b) & 0x0001) ) { __unlock_io(pthread_ptr,ofile_lst[desc].desc,O_WRONLY); //yes isset=1 or wait =1 then select is terminated } } //reset file descriptor vector if(!count) { if(readfds) memset(readfds,0,sizeof(fd_set)); if(writefds) memset(writefds,0,sizeof(fd_set)); if(errorfds) memset(errorfds,0,sizeof(fd_set)); } return count; }
/** * \brief Start listening to the specified port. Standard BSD listen() with internal name. * \param[in] desc is a socket that has been created with socket(), bound to a local address with bind(), and is listening for connections after a listen(). * \param[out] address is a pointer to a \ref _sockaddr structure. This structure is filled in with the address of the peer socket, as known to the communications layer. The format is always IPv6 in this implementation. * \param[in,out] len is a value-result argument: it should initially contain the size of the structure pointed to by \p address; on return it will contain the actual length (in bytes) of the address returned. * \details The accept() system call is used with connection-based socket types (\ref SOCK_STREAM only in this implementation). It extracts the first connection request on the queue of pending connections, creates a new connected socket, and returns a new file descriptor referring to that socket. The newly created socket is not in the listening state. The original socket \p desc is unaffected by this call. * \note Details may be added on blocking/non-blocking behavior. * \return On connection success, zero is returned. On error, -1 is returned. * \callgraph */ int _sys_sock_accept(int fd, struct _sockaddr *address,int* len){ #if defined (__KERNEL_NET_IPSTACK) && defined (USE_UIP_CORE) pid_t pid; kernel_pthread_t* pthread_ptr; hsock_t hsock = 0; hsock_t hcsock = 0; desc_t desc; if(!(pthread_ptr = kernel_pthread_self())){ __set_kernel_pthread_errno(ESRCH); return -1; } if((pid=pthread_ptr->pid)<=0){ __set_kernel_pthread_errno(ESRCH); return -1; } // if(fd<0){ __set_kernel_pthread_errno (EBADF); return -1; } // desc = process_lst[pid]->desc_tbl[fd]; if(desc<0){ __set_kernel_pthread_errno (EBADF); return -1; } if(!ofile_lst[desc].used){ __set_kernel_pthread_errno (EBADF); return -1; } if(! (hsock = ofile_lst[desc].p) ){ __set_kernel_pthread_errno (ENOTSOCK); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_CLOSED){ __set_kernel_pthread_errno (ENOTCONN); return -1; } if( ((socket_t*)(hsock))->state==STATE_SOCKET_ABORTED){ __set_kernel_pthread_errno (ECONNABORTED); return -1; } if(((socket_t*)hsock)->protocol!=IPPROTO_TCP){ __set_kernel_pthread_errno (EPROTONOSUPPORT); return -1; } //Make ready to accept connection ((socket_t*)hsock)->state = STATE_SOCKET_LISTEN; //wait connected operation from socketEngine __WAIT_SOCKET_EVENT(pthread_ptr,hsock); if(!ofile_lst[desc].used){ __set_kernel_pthread_errno (EINVAL); return -1; } if(! (hsock = ofile_lst[desc].p) ){ __set_kernel_pthread_errno (ENOTSOCK); return -1; } if(((socket_t*)hsock)->state!=STATE_SOCKET_CONNECTED){ __set_kernel_pthread_errno (ENOTCONN); return -1; } //((socket_t*)hsock)->state=STATE_SOCKET_ACCEPTED; //wait Accepted operation from socketEngine //__WAIT_SOCKET_EVENT(hsock); // hcsock = ((socket_t*)hsock)->hsocks; // #if UIP_CONF_IPV6 memcpy(address,&((socket_t*)hcsock)->addr_in,sizeof(struct _sockaddr_in6)); // *len=sizeof(struct _sockaddr_in6); // #else ((struct _sockaddr_in*)address)->sin_port = ((socket_t*)hcsock)->addr_in.sin_port; ((struct _sockaddr_in*)address)->sin_addr.s_addr = ((socket_t*)hcsock)->addr_in.sin_addr.s_addr; // *len=sizeof(struct _sockaddr_in); // #endif /*if(((socket_t*)hsock)->state!=STATE_SOCKET_LISTEN) return NULL;*/ // __set_kernel_pthread_errno (0); // return ((socket_t*)hcsock)->fd; #else return -1; #endif } //end of _sys_sock_accept()