📄 ul_l_drv_eth.c
字号:
/******************************************************************* uLan Communication - basic library ul_l_drv_eth.c - ethernet driver interface (C) Copyright 1996,1999 by Pavel Pisa The uLan driver is distributed under the Gnu General Public Licence. See file COPYING for details. *******************************************************************/#include <stdio.h>#include <string.h>#include <stdlib.h>#ifndef _WIN32#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <signal.h>#define BAD_SOCKET(s) ((s) < 0)#define UL_SOCKET_INVALID -1#define SLEEP(x) sleep(x)#else#include <winsock.h>#include <fcntl.h>#define BAD_SOCKET(s) ((s) == INVALID_SOCKET)#define UL_SOCKET_INVALID INVALID_SOCKET#define SLEEP(x) Sleep(x*1000)#endif#include <ul_gavlcust.h>#include <ul_msg_buf.h>#include <ul_l_drv_eth.h>#include <ul_list.h>#ifdef CONFIG_OC_ULUT#include <ul_log.h>ul_log_domain_t ulogd_drv_eth = {0, "drv_eth"};#define UL_LDOMAIN (&ulogd_drv_eth)#else#include <ul_lib/ul_l_log.h>#define UL_LDOMAIN NULL#endif#ifdef _WIN32 typedef SOCKET ul_fd_sock_t;#else /*_WIN32*/ typedef int ul_fd_sock_t; #define closesocket(s) close(s)#endif /*_WIN32*/typedef struct msgbuff_inproc_item { gavl_node_t node; ul_msg_buf_t *msgbuff; unsigned stamp;} msgbuff_inproc_item_t;typedef struct msgbuff_inproc_root { gavl_cust_root_field_t root;} msgbuff_inproc_root_t; typedef unsigned msgbuff_inproc_key_t; GAVL_CUST_NODE_INT_DEC(msgbuff_inproc, msgbuff_inproc_root_t, msgbuff_inproc_item_t, msgbuff_inproc_key_t, root, node, stamp, msgbuff_inproc_cmp_fnc) inline intmsgbuff_inproc_cmp_fnc(const msgbuff_inproc_key_t *a, const msgbuff_inproc_key_t *b){ if (*a>*b) return 1; if (*a<*b) return -1; return 0;} GAVL_CUST_NODE_INT_IMP(msgbuff_inproc, msgbuff_inproc_root_t, msgbuff_inproc_item_t, msgbuff_inproc_key_t, root, node, stamp, msgbuff_inproc_cmp_fnc) typedef struct filter_inproc_item { ul_list_node_t node; ul_msginfo msginfo;} filter_inproc_item_t;typedef struct ul_fd_eth_context_t { ul_fd_context_t context; ul_fd_sock_t sock_fd; FILE *sock_wfile; uint32_t ipaddress; uint16_t port; ul_dbuff_t dev_name; ul_dbuff_t rcvbuff; ul_msg_buf_t *msgbuff_start; ul_msg_buf_t *msgbuff_proc; int msgbuff_idx; int msg_received_flg; unsigned stamp_eth_cnt; msgbuff_inproc_root_t msgbuff_inproc_root; ul_list_head_t filter_inproc_root;} ul_fd_eth_context_t;UL_LIST_CUST_DEC(filter_inproc, ul_fd_eth_context_t,filter_inproc_item_t, filter_inproc_root,node);/* forward declarations */int ul_eth_close(ul_fd_t ul_fd);int ul_eth_recv_responce_int(ul_fd_eth_context_t *eth_fd,const char *cmd,int sn,int *v);static inlineul_fd_eth_context_t *ul_fd2eth_context(ul_fd_t ul_fd){ return UL_CONTAINEROF(ul_fd, ul_fd_eth_context_t, context);}static inlineul_fd_sock_t ulop_eth_fd2sock_fd(ul_fd_t ul_fd){ if(ul_fd==UL_FD_INVALID) return UL_FD_DIRECT_INVALID; else return ul_fd2eth_context(ul_fd)->sock_fd;}ul_fd_direct_t ulop_eth_fd2sys_fd(ul_fd_t ul_fd){ /* * This is not fully correct on Windows, there does not exist handle * type usable for both files and sockets */ return ulop_eth_fd2sock_fd(ul_fd);}unsigned ul_eth_gen_stamp(ul_fd_eth_context_t *eth_fd){ eth_fd->stamp_eth_cnt++; eth_fd->stamp_eth_cnt&=0x7fffffff; if(!eth_fd->stamp_eth_cnt)eth_fd->stamp_eth_cnt++; return eth_fd->stamp_eth_cnt; };ul_fd_sock_t ul_eth_sock_init(uint32_t net_ipaddr,uint16_t net_port) { struct sockaddr_in name; ul_fd_sock_t fd; #ifdef _WIN32 WORD wVersionRequested; WSADATA wsaData; int sockopt = SO_SYNCHRONOUS_NONALERT; #endif #ifdef _WIN32 wVersionRequested = MAKEWORD(2, 0); WSAStartup(wVersionRequested, &wsaData); setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&sockopt, sizeof(sockopt)); #endif #ifndef _WIN32 signal(SIGPIPE, SIG_IGN); #endif if (BAD_SOCKET(fd=socket(AF_INET, SOCK_STREAM, 0))) return UL_SOCKET_INVALID; name.sin_family=AF_INET; name.sin_addr.s_addr=net_ipaddr; name.sin_port=net_port; if (BAD_SOCKET(connect(fd, (struct sockaddr *) &name, sizeof(name)))) { closesocket(fd); return UL_SOCKET_INVALID; } return fd;}intul_eth_sock_init_file(ul_fd_eth_context_t *eth_fd){ int f; #ifndef _WIN32 f=eth_fd->sock_fd; #else f=_open_osfhandle(eth_fd->sock_fd,0); if (f<0) return -1; #endif /* _WIN32 */ eth_fd->sock_wfile=fdopen(f,"w"); if (!eth_fd->sock_wfile) return -1; return 0;}int ul_eth_sock_close(ul_fd_eth_context_t *eth_fd){ if (eth_fd->sock_wfile) fclose(eth_fd->sock_wfile); eth_fd->sock_wfile=0; if (eth_fd->sock_fd!=UL_SOCKET_INVALID) closesocket(eth_fd->sock_fd); eth_fd->sock_fd=UL_SOCKET_INVALID; return 0;}intul_eth_sock_reinit(ul_fd_eth_context_t *eth_fd){ int i,v; unsigned eth_stamp; filter_inproc_item_t *fitem; if (eth_fd->sock_fd!=UL_SOCKET_INVALID) return 0; eth_fd->sock_fd=ul_eth_sock_init(eth_fd->ipaddress,eth_fd->port); if (eth_fd->sock_fd==UL_SOCKET_INVALID) return -1; if (ul_eth_sock_init_file(eth_fd)) return -1; /* send command to server request */ eth_stamp=ul_eth_gen_stamp(eth_fd); fprintf(eth_fd->sock_wfile,"usc %d open %s\n",eth_stamp,eth_fd->dev_name.data); fflush(eth_fd->sock_wfile); /* wait for responce */ i=ul_eth_recv_responce_int(eth_fd,"open",eth_stamp,&v); if ((i!=1) || (v==0)) { ul_eth_sock_close(eth_fd); return -1; } /* create filters */ ul_list_for_each(filter_inproc,eth_fd,fitem) { ul_msginfo *msginfo=&fitem->msginfo; eth_stamp=ul_eth_gen_stamp(eth_fd); fprintf(eth_fd->sock_wfile,"usc %d addfilt %02x%02x%02x\n",eth_stamp,msginfo->sadr,msginfo->dadr,msginfo->cmd); fflush(eth_fd->sock_wfile); /* wait for responce */ if (ul_eth_recv_responce_int(eth_fd,"addfilt",eth_stamp,&v)!=1) { ul_eth_sock_close(eth_fd); return -1; } } return 0;}static inline intul_eth_sock_check(ul_fd_eth_context_t *eth_fd){ return ul_eth_sock_reinit(eth_fd);}/** * ul_eth_recv_msg - * @fd: * @rcvbuff: * @timeout: * * Returns number of received bytes or negative error code * Error codes: -1 connection was terminated by server * -2 xxx * -3 memory allocation error * -4 timeout * -5 terminated */intul_eth_recv_msg(int fd,ul_dbuff_t *rcvbuff,int timeout, int *terminated){ ul_dbuff_set_len(rcvbuff, 0); while ((*terminated)==0) { struct timeval stimeout = {1, 0}; int r,nread; fd_set fds; FD_ZERO(&fds); FD_SET(fd,&fds); r=select(FD_SETSIZE,&fds,NULL,NULL,&stimeout); if (timeout>0) { timeout--; if (!timeout) return -4; } if (r<0) { return -1; } if (r==0) continue; if(FD_ISSET(fd, &fds)) { #ifndef _WIN32 ioctl(fd, FIONREAD, &nread); #else u_long unread; ioctlsocket(fd, FIONREAD, &unread); nread=unread; #endif /* _WIN32 */ if(nread != 0) { int n; int old_len = rcvbuff->len; int new_len = old_len + nread; int eofmsg = 0; if(ul_dbuff_set_len(rcvbuff, new_len) == new_len) { nread = recv(fd, rcvbuff->data + old_len, nread,0); // try to find '\10' in new data to check out the on of message for(n = nread-1; n>=0; n--) { if((rcvbuff->data + old_len)[n] == 10) { eofmsg = 1; break; } } } else { /* Can't allocate memory */ return -3; } if(eofmsg) { // if you got the whole message append terminating 0 & process it ul_dbuff_append_byte(rcvbuff, '\0'); ul_dbuff_trim(rcvbuff); return rcvbuff->len; } } else return -1; } else { // this should never happen if the program work well // outread unexpected data from buffer int fd; for(fd = 0; fd < FD_SETSIZE; fd++) { if(FD_ISSET(fd, &fds)) { ul_dbuff_set_len(rcvbuff, 128); nread = recv(fd, rcvbuff->data, rcvbuff->len-1,0); rcvbuff->data[nread] = '\0'; } } } } return -5;}intul_eth_send_msg(FILE *fd,ul_msg_buf_t *sndbuff){ ul_msginfo *msginfo; int i; do{ msginfo=&sndbuff->msginfo; fprintf(fd,"%02x%02x%02x%04x%08x%04x", msginfo->sadr,msginfo->dadr,msginfo->cmd, msginfo->flg,msginfo->stamp,msginfo->len); ul_log(UL_LDOMAIN,UL_LOGL_DEB|UL_LOGL_CONT,"%02x%02x%02x%04x%08x%04x", msginfo->sadr,msginfo->dadr,msginfo->cmd, msginfo->flg,msginfo->stamp,msginfo->len); i=0; while(i<msginfo->len) { fprintf(fd,"%02x",sndbuff->data.data[i]); ul_log(UL_LDOMAIN,UL_LOGL_DEB|UL_LOGL_CONT,"%02x",sndbuff->data.data[i]); i++; } if (!sndbuff->tail) return 0; sndbuff=sndbuff->tail; }while(1);}intul_eth_demarshal_stream(ul_msg_buf_t *msg_buf,char *stream,int stream_len){ ul_msg_buf_t *tail; ul_msginfo *msginfo; int r,i,v; ul_msg_buf_destroy(msg_buf); do { /* header */ msginfo=&msg_buf->msginfo; if (stream_len<22) return -1; r=sscanf(stream,"%02x%02x%02x%04x%08x%04x", &msginfo->sadr,&msginfo->dadr,&msginfo->cmd, &msginfo->flg,&msginfo->stamp,&msginfo->len); stream+=22; stream_len-=22; if ((stream_len/2)<msginfo->len) return -1; if (ul_dbuff_prep(&msg_buf->data,msginfo->len)<msginfo->len) return -1; /* copy data from txt stream to ul_msg_buf */ i=0; while (i<msginfo->len) { sscanf(stream,"%02x",&v); *(msg_buf->data.data+i)=v; stream+=2; i++; } stream_len-=2*i; /* prepare tail */ if (stream_len>0) { if(!(tail=malloc(sizeof(ul_msg_buf_t)))) return -1; ul_msg_buf_init(tail); msg_buf->tail=tail; msg_buf=tail; } } while(stream_len>0); return 1;} intul_eth_recv_responce_int(ul_fd_eth_context_t *eth_fd,const char *cmd,int sn,int *v){ char buff[64]; int r,t=0; r=ul_eth_recv_msg(eth_fd->sock_fd,ð_fd->rcvbuff,UL_ETH_SOCK_TIMEOUT,&t); if (r<0) { if (r==-1) ul_eth_sock_close(eth_fd); return r; } sprintf(buff,"usr %d %s %%d",sn,cmd); return sscanf((char*)eth_fd->rcvbuff.data,buff,v);}intul_eth_recv_responce_msgbuf(ul_fd_eth_context_t *eth_fd,const char *cmd,int sn,ul_msg_buf_t *rdbuf){ char *msg_header,*msg_sn,*msg_cmd,*msg_data; int msg_data_len,i,r,t=0; r=ul_eth_recv_msg(eth_fd->sock_fd,ð_fd->rcvbuff,UL_ETH_SOCK_TIMEOUT,&t); if (r<0) { if (r==-1) ul_eth_sock_close(eth_fd); return r; } msg_header = strtok ((char*)eth_fd->rcvbuff.data," "); if (msg_header!=NULL) { msg_sn = strtok (NULL," "); if (msg_sn!=NULL) { msg_cmd = strtok (NULL," "); if (msg_cmd!=NULL) { msg_data = strtok (NULL," "); msg_data_len=0; if (msg_data!=NULL) msg_data_len=eth_fd->rcvbuff.len-(msg_data-(char*)eth_fd->rcvbuff.data)-1; if (strcmp(cmd,msg_cmd)!=0) return -1; i=strtol(msg_sn,NULL,0); if (sn!=i) return -1; return ul_eth_demarshal_stream(rdbuf,msg_data,msg_data_len); } } } return -1;}ul_fd_ops_t ul_fd_eth_ops;static inline ul_fd_t ul_fd_direct2ul_fd(ul_fd_sock_t fd){ ul_fd_eth_context_t *eth_fd; if (fd==UL_SOCKET_INVALID) return UL_FD_INVALID; eth_fd=malloc(sizeof(*eth_fd)); if(!eth_fd) return UL_FD_INVALID; memset(eth_fd,0,sizeof(*eth_fd)); eth_fd->sock_fd=fd; eth_fd->context.fd_ops=&ul_fd_eth_ops; ul_dbuff_init(ð_fd->rcvbuff, 0); ul_dbuff_init(ð_fd->dev_name, 0); filter_inproc_init_head(eth_fd); msgbuff_inproc_init_root_field(ð_fd->msgbuff_inproc_root); return ð_fd->context;}ul_fd_t ul_eth_open(const char *dev_name, const char *options){ ul_fd_eth_context_t *eth_fd; ul_fd_t r; char buff[128],*d; uint32_t eth_ipaddr; uint16_t eth_port; int i,v,l; unsigned eth_stamp; ul_fd_sock_t sock_fd; if(dev_name==NULL) dev_name=UL_DEV_NAME; else if(!strncmp(dev_name,"eth:",4)) dev_name+=4;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -