int peisk_recvBlocking(int fd,void *buf,size_t len,int flags,double timeout) { int i, new_bytes; char *data=(char*)buf; double t0 = peisk_gettimef(); while(len>0) { errno=0; new_bytes=recv(fd,data,len,flags|MSG_NOSIGNAL); if(errno == EPIPE || new_bytes == 0) { /* Broken pipe - close socket and return */ for(i=0;i<PEISK_MAX_CONNECTIONS;i++) { if(peisk_printLevel & PEISK_PRINT_CONNECTIONS) printf("Connection %d socket=%d\n",i,peiskernel.connections[i].connection.tcp.socket); if(peiskernel.connections[i].id != -1 && peiskernel.connections[i].connection.tcp.socket == fd) peisk_closeConnection(peiskernel.connections[i].id); } /*printf("<\n"); fflush(stdout); */ return 0; } if(new_bytes == -1) peisk_waitForRead(fd,0.01); /* was: usleep 0 */ else { if(new_bytes == 0) if(peisk_printLevel & PEISK_PRINT_CONNECTIONS) printf("peisk: error - not getting any bytes, broken connection?\n"); len -= new_bytes; data+=new_bytes; } if(peisk_gettimef() > t0 + timeout) { /*printf("< (TIME)\n"); fflush(stdout);*/ return 0; } /* Timeout reached */ } return 1; }
int peisk_bluetoothReceiveIncomming(struct PeisConnection *connection,struct PeisPackage *package) { int status; double t0, t1; static float lastReceive=0.0; /* For debugging only */ errno=0; t0 = peisk_gettimef(); status=recv(connection->connection.bluetooth.socket,(void*)package,sizeof(PeisPackage),MSG_NOSIGNAL); t1 = peisk_gettimef(); if(t1 - t0 > 0.1) { printf("Receive took %.3fs\n",t1-t0); } if(errno == EAGAIN || status == 0) return 0; /* Nothing received, come back later */ if(status > 0) { peisk_logTimeStamp(stdout); printf("BT receive: %d bytes, sock: %d ",status,connection->connection.bluetooth.socket); /*peisk_hexDump(package,status);*/ peisk_printNetPackageInfo(package); lastReceive = peisk_timeNow; } if(errno == EPIPE || status == -1) { /* Error - close socket */ if(1 || peisk_printLevel & PEISK_PRINT_CONNECTIONS) { peisk_logTimeStamp(stdout); printf("peisk: warning - error EPIPE in BT receive, closing socket status: %d\n",status); perror(""); printf("Time since last read: %.1fs\n",peisk_timeNow - lastReceive); } peisk_closeConnection(connection->id); return 0; } if(status < sizeof(package->header)) { /* For L2CAP it is an error to not receive the full data in each recv operation. */ fprintf(stderr,"Warning, only got partial data on BT connection\n"); peisk_closeConnection(connection->id); return 0; } if(ntohs(package->header.datalen) > PEISK_MAX_PACKAGE_SIZE) { /* Check for bad package length */ if(1 || peisk_printLevel & PEISK_PRINT_CONNECTIONS) fprintf(stdout,"peisk: error, too large (%d) package received on BT connection %d\n",package->header.datalen,connection->id); /*peisk_syncflush(connection);*/ peisk_closeConnection(connection->id); return 0; } return 1; }
void peisk_bluetoothConnectOutgoing() { int i; PeisBluetoothAdaptor *adaptor; int status=0; for(i=0;i<peisk_nBluetoothAdaptors;i++) { adaptor = &peisk_bluetoothAdaptors[i]; if(adaptor->outgoing.mode == 0) continue; if(adaptor->outgoing.mode == 1) { /* See if connect() have finished */ struct pollfd fds; fds.fd = adaptor->outgoing.socket; fds.events = -1; fds.revents = 0; if(poll(&fds,1,0)) { socklen_t slen; slen=sizeof(status); if(getsockopt(adaptor->outgoing.socket,SOL_SOCKET,SO_ERROR,(void*) &status,&slen)) { printf("Get sockopt failed...\n"); } printf("Connection finished: status=0x%x (time elapsed: %.3fs)\n",status, peisk_gettimef()-adaptor->outgoing.timeout+PEISK_CONNECT_TIMEOUT); if(status) { printf("Outgoing connection failed: "); perror(""); printf("\n"); peisk_abortConnect(adaptor->outgoing.connection); close(adaptor->outgoing.socket); adaptor->outgoing.mode = 0; } else { adaptor->outgoing.connection->type=eBluetoothConnection; adaptor->outgoing.connection->connection.bluetooth.adaptor=adaptor; adaptor->outgoing.connection->connection.bluetooth.socket=adaptor->outgoing.socket; printf("Outgoing connection %x has id %d\n", (unsigned int) adaptor->outgoing.connection,adaptor->outgoing.connection->id); PeisConnectMessage message; peisk_initConnectMessage(&message,adaptor->outgoing.flags); printf("Sending connection message:\n"); peisk_hexDump(&message,sizeof(message)); printf("\n"); send(adaptor->outgoing.socket,&message,sizeof(message),MSG_NOSIGNAL); peisk_outgoingConnectFinished(adaptor->outgoing.connection,adaptor->outgoing.flags); if(1 || peisk_printLevel & PEISK_PRINT_CONNECTIONS) fprintf(stdout,"peisk: new outbound BLUETOOTH connection established\n"); adaptor->outgoing.mode = 0; } } } if(adaptor->outgoing.timeout < peisk_timeNow && adaptor->outgoing.mode != 0) { printf("Giving up on outgoing CONNECT\n"); peisk_abortConnect(adaptor->outgoing.connection); close(adaptor->outgoing.socket); adaptor->outgoing.mode = 0; } } }
void peisk_registerPeriodicWithName(double period,void *data,PeisPeriodic *hook,char *name) { int i; for(i=0;i<PEISK_MAX_PERIODICS;i++) if(peiskernel.periodics[i].periodicity == -1.0) break; if(i == PEISK_MAX_PERIODICS) { fprintf(stderr,"peisk: error, too many periodic functions registered\n"); exit(0); } peiskernel.periodics[i].periodicity = period; peiskernel.periodics[i].data = data; peiskernel.periodics[i].hook = hook; peiskernel.periodics[i].last = peisk_gettimef(); peiskernel.periodics[i].name = name; if(i > peiskernel.highestPeriodic) peiskernel.highestPeriodic = i; }
void peisk_wait(int useconds) { double t0=peisk_gettimef()+1e-6*useconds; fd_set readSet, writeSet, excpSet; int n=0; int ret; #ifdef GUMSTIX struct timeval timeout; #else struct timespec timeout; #endif double offset=peiskernel.timeOffset[0] + 1e-6*peiskernel.timeOffset[1]; double offset2; peisk_step(); while(peisk_int_isRunning) { /* Compensate if kernel clock has changed */ offset2=peiskernel.timeOffset[0]+1e-6*peiskernel.timeOffset[1]; if(fabs(offset2 - offset) > 0.1) { /*printf("adjusting time to sleep to with %f secs\n",offset2-offset);*/ t0 += offset2-offset; offset=offset2; } timeout.tv_sec = 0; #ifdef GUMSTIX timeout.tv_usec = MIN((int)1e4, (int)(1e6 * fmod((t0 - peisk_gettimef()),1.0))); if(timeout.tv_usec <= 0) break; #else timeout.tv_nsec = MIN((int)1e7, (int)(1e9 * fmod((t0 - peisk_gettimef()),1.0))); if(timeout.tv_nsec <= 0) break; #endif FD_ZERO(&readSet); FD_ZERO(&writeSet); FD_ZERO(&excpSet); n=0; if(peiskernel.avgStepTime < 0.005) { /* Perform a forced sleep if we are running to quickly to compensate for the pselect bug */ } else { /* Perform a normal sleep for 10ms or until we have new data available */ peisk_setSelectReadSignals(&n,&readSet,&writeSet,&excpSet); } errno=0; #ifdef GUMSTIX ret=select(n,&readSet,&writeSet,&excpSet,&timeout); #else ret=pselect(n,&readSet,&writeSet,&excpSet,&timeout,NULL); #endif if(ret == -1) perror("peisk_wait::select"); /* double t1=peisk_gettimef(); if(t1 - t0 < 0.0001) { printf("sleep: %3.6f nsec=%d ret=%d ",t1-t0,timeout.tv_nsec,ret); int i; printf("FD: "); for(i=0;i<n;i++) { if(FD_ISSET(i,&readSet)) printf("r%d ",i); if(FD_ISSET(i,&writeSet)) printf("w%d ",i); if(FD_ISSET(i,&excpSet)) printf("e%d ",i); } printf("\n"); fflush(stdout); }*/ peisk_step(); } }
void peisk_initialize(int *argc,char **args) { int i, j; char name[256]; char *hostname, *progname; unsigned char *ip; char tmp[256]; int t0,t1; PeisConnectionMgrInfo *connMgrInfo; if(peisk_int_isRunning) peisk_shutdown(); peisk_getrawtime2(&t0,&t1); srand((int) t1); peiskernel.id = rand() % 10000; peiskernel.tcp_serverPort=8000; peiskernel.udp_serverPort=8000; peiskernel.tcp_isListening=0; peiskernel.lastStep = peisk_gettimef(); peiskernel.nextConnectionId = 1; peisk_printLevel = 0; peiskernel.highestPeriodic=0; peiskernel.highestConnection=0; hostname = NULL; peiskernel.isLeaf=0; peiskernel.timeOffset[0]=0; peiskernel.timeOffset[1]=0; peiskernel.isTimeMaster=0; peiskernel.avgStepTime=0.1; peiskernel.incomingTraffic=0; peiskernel.outgoingTraffic=0; peiskernel.nAcknowledgementPackages=0; peiskernel.deadhostHook = NULL; peiskernel.nAckHooks = 0; peiskernel.tick = 0; peiskernel.broadcastingCounter = 0; peisk_cl_user = getenv("USER"); if(!peisk_cl_user) peisk_cl_user = "******"; signal(SIGINT, peisk_trapCtrlC); signal(SIGTERM, peisk_trapCtrlC); signal(SIGPIPE, peisk_trapPipe); peiskernel_initNetInterfaces(); for(i=0;i<PEISK_MAX_CONNECTIONS;i++) { peiskernel.connections[i].id=-1; peiskernel.connections[i].routingTable = NULL; for(j=0;j<PEISK_MAX_ROUTING_PAGES;j++) peiskernel.connections[i].routingPages[j] = NULL; } peiskernel.freeQueuedPackages=NULL; peiskernel.nDirConnReqs=0; peiskernel.doShutdown=0; for(i=0;i<PEISK_NPORTS;i++) peiskernel.hooks[i]=NULL; for(i=0;i<PEISK_MAX_PERIODICS;i++) peiskernel.periodics[i].periodicity=-1.0; for(i=0;i<PEISK_MAX_LONG_MESSAGES;i++) { peiskernel.assemblyBuffers[i].seqid = 0; peiskernel.assemblyBuffers[i].seqlen = 0; peiskernel.assemblyBuffers[i].allocated_seqlen = 0; peiskernel.assemblyBuffers[i].received = NULL; peiskernel.assemblyBuffers[i].data = NULL; } peiskernel.routingTable = peisk_hashTable_create(PeisHashTableKey_Integer); if(peiskernel.routingTable == NULL) { fprintf(stderr,"peisk: error, failed to create routing table\n"); exit(-1); } for(i=0;i<PEISK_LOOPINFO_HASH_SIZE;i++) peiskernel.loopHashTable[i]=-1; for(i=0;i<PEISK_LOOPINFO_SIZE;i++) peiskernel.loopTable[i].id=-1; peisk_initBluetooth(); peisk_initP2PLayer(); peisk_registerDefaultServices(); //peisk_getOptions(argc,args); peisk_parseOptions(NULL,"command-line"); peisk_restartServer(); if(peiskernel.tcp_isListening) if(peisk_printLevel & PEISK_PRINT_STATUS) printf("peisk: serving at port %d\n",peiskernel.tcp_serverPort); peisk_id = peiskernel.id; peiskernel.magicId = rand(); peisk_registerDefaultServices2(); hostname=peisk_cl_hostname; if(!hostname) hostname=getenv("HOSTNAME"); if(!hostname) { FILE *fp = fopen("/etc/hostname","r"); if(!fp) fp = fopen("/etc/HOSTNAME","r"); if(!fp) { if(system("hostname > /tmp/peisk_cl_hostname")!=-1) fp = fopen("/tmp/peisk_cl_hostname","r"); } if(fp) { if(!fgets(name,255,fp)) sprintf(name,"johndoe"); fclose(fp); for(i=0;i<255&&name[i];i++) if(name[i]=='\n' || name[i]==' ' || name[i] == '.') name[i]=0; hostname=strdup(name); } else { char name[256]; sprintf(name,"johndoe-%d",peisk_id / 100); hostname=strdup(name); } } for(i=0;i<255;i++) { if(hostname[i] == 0 || hostname[i] == '.' || hostname[i] == ' ') break; else name[i] = hostname[i]; } name[i]=0; if(peisk_cl_componentName) progname=peisk_cl_componentName; else { for(progname = args[0]+strlen(args[0]);progname>=args[0]&&*progname!='/';progname--) {} progname++; } peiskernel.hostInfo.id = peiskernel.id; peiskernel.hostInfo.magic = peiskernel.magicId; peiskernel.hostInfo.networkCluster = peiskernel.id; int mypid = getpid(); snprintf(peiskernel.hostInfo.fullname,sizeof(peiskernel.hostInfo.fullname),"%s@%s!%d",progname,name,mypid); snprintf(peiskernel.hostInfo.hostname,sizeof(peiskernel.hostInfo.hostname),"%s",name); peisk_setStringTuple("kernel.hostname",peiskernel.hostInfo.hostname); snprintf(tmp,sizeof(tmp),"v%lf (proto %d)",1.0,peisk_protocollVersion); peisk_setStringTuple("kernel.version",tmp); peisk_setStringTuple("kernel.name",progname); peisk_setStringTuple("kernel.do-quit",""); peisk_setStringTuple("kernel.user",peisk_cl_user); snprintf(tmp,sizeof(tmp),"%d",peiskernel.id); peisk_setStringTuple("kernel.id",tmp); if(peisk_printLevel & PEISK_PRINT_STATUS) printf("peisk #%d: started\n",peisk_id); peiskernel.hostInfo.nLowlevelAddresses=0; if(peiskernel.tcp_isListening) { for(i=0,j=peiskernel.hostInfo.nLowlevelAddresses;i<peisk_nInetInterfaces;i++) { if(peiskernel.isLeaf && !peisk_inetInterface[i].isLoopback) continue; if(peiskernel.udp_serverPort != 0 && 0) { peiskernel.hostInfo.lowAddr[j].type = ePeisUdpIPv4; ip = (unsigned char *)&peisk_inetInterface[i].ip; peiskernel.hostInfo.lowAddr[j].addr.udpIPv4.ip[0]=ip[0]; peiskernel.hostInfo.lowAddr[j].addr.udpIPv4.ip[1]=ip[1]; peiskernel.hostInfo.lowAddr[j].addr.udpIPv4.ip[2]=ip[2]; peiskernel.hostInfo.lowAddr[j].addr.udpIPv4.ip[3]=ip[3]; peiskernel.hostInfo.lowAddr[j].addr.udpIPv4.port=peiskernel.udp_serverPort; } else { peiskernel.hostInfo.lowAddr[j].type = ePeisTcpIPv4; ip = (unsigned char *)&peisk_inetInterface[i].ip; peiskernel.hostInfo.lowAddr[j].addr.tcpIPv4.ip[0]=ip[0]; peiskernel.hostInfo.lowAddr[j].addr.tcpIPv4.ip[1]=ip[1]; peiskernel.hostInfo.lowAddr[j].addr.tcpIPv4.ip[2]=ip[2]; peiskernel.hostInfo.lowAddr[j].addr.tcpIPv4.ip[3]=ip[3]; peiskernel.hostInfo.lowAddr[j].addr.tcpIPv4.port=peiskernel.tcp_serverPort; } strncpy(peiskernel.hostInfo.lowAddr[j].deviceName,peisk_inetInterface[i].name,sizeof(peiskernel.hostInfo.lowAddr[i].deviceName)); peiskernel.hostInfo.lowAddr[j].isLoopback = peisk_inetInterface[i].isLoopback ? 1 : 0; j++; } peiskernel.hostInfo.nLowlevelAddresses=j; } peisk_addBluetoothLowlevelAddresses(); peiskernel.hostInfoHT = peisk_hashTable_create(PeisHashTableKey_Integer); peiskernel.connectionMgrInfoHT = peisk_hashTable_create(PeisHashTableKey_Integer); peisk_insertHostInfo(peiskernel.id,&peiskernel.hostInfo); connMgrInfo = (PeisConnectionMgrInfo*) malloc(sizeof(PeisConnectionMgrInfo)); peisk_insertConnectionMgrInfo(peiskernel.id,connMgrInfo); connMgrInfo->nTries = 0; connMgrInfo->nextRetry = peisk_timeNow; connMgrInfo->usefullTraffic=0; connMgrInfo->lastUsefullTraffic=0; printf("PeisKernel v%lf (protocoll %d)@%s %s ",1.0,peisk_protocollVersion,__DATE__,__TIME__); peisk_printHostInfo(&peiskernel.hostInfo); peisk_int_isRunning=1; PeisRoutingInfo *routingInfo; if(peisk_hashTable_getValue(peiskernel.routingTable,(void*)(intA)peiskernel.id,(void**)(void*)&routingInfo) == 0) { PEISK_ASSERT(routingInfo->connection == NULL,("Route to ourselves points to nonzero connection\n")); } }
void peisk_logTimeStamp(FILE *stream) { fprintf(stream,"%3.2f ",fmod(peisk_gettimef(),1000)); }