int receiveMessage(int sock, void *message, int maxLength, unsigned long timeout) { unsigned long val; long timeout_s; long timeout_us; int bytesReceived; if (sock < 0) { // invalid socket number. return -1; } // set a receive timeout val = timeout + 100; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &val, sizeof(unsigned long)); timeout_s = timeout / 1000; timeout_us = (timeout - (timeout_s*1000)) * 1000; bytesReceived = 0; switch (recvfromTimeOut(sock, timeout_s, timeout_us)) { case 0: // timed out case -1: // error return -1; break; default: // got a reply bytesReceived = recv(sock, message, maxLength, 0); break; } return bytesReceived; }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { char address [1024] ; char port [1024] ; char key [1024] ; struct addrinfo servHints ; struct addrinfo *servInfo ; int status ; enum {IN_HOST, IN_PORT, IN_KEY} ; enum {OUT_GO} ; if (nin != 3) { mexErrMsgTxt("Three arguments required") ; } if (mxGetString(in[IN_HOST], address, sizeof(address))) { mexErrMsgTxt("HOST must be a string") ; } if (mxGetString(in[IN_PORT], port, sizeof(port))) { mexErrMsgTxt("PORT must be a string") ; } if (mxGetString(in[IN_KEY], key, sizeof(key))) { mexErrMsgTxt("KEY must be a string") ; } /* IN address of server */ memset(&servHints, 0, sizeof(servHints)); servHints.ai_family = AF_INET ; /* AF_UNSPEC */ servHints.ai_socktype = SOCK_DGRAM ; status = getaddrinfo(address, port, &servHints, &servInfo) ; if (status) { mexPrintf(gai_strerror(status)) ; mexErrMsgTxt("getaddrinfo") ; } #if 1 { struct addrinfo *p ; for(p = servInfo ; p != NULL ; p = p->ai_next) { void *addr; char *ipver; char ipstr[INET6_ADDRSTRLEN]; int port ; /* get the pointer to the address itself, * different fields in IPv4 and IPv6: */ if (p->ai_family == AF_INET) { /* IPv4 */ struct sockaddr_in *ipv4 = (struct sockaddr_in *) p->ai_addr ; addr = &(ipv4->sin_addr); port = ntohs(ipv4->sin_port) ; ipver = "IPv4"; } else { /* IPv6 */ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; addr = &(ipv6->sin6_addr); port = ntohs(ipv6->sin6_port) ; ipver = "IPv6"; } /* convert the IP to a string and print it: */ inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); mexPrintf(" %s: %s (port %d)\n", ipver, ipstr, port); } } #endif { char answer [1024] ; int unsigned answerLength = sizeof(answer) ; int answerRecvLength ; int clientSocket ; socklen_t fromLength = sizeof(struct sockaddr_in) ; int numAttemptsLeft = 5 ; memset(answer, 0, answerLength) ; clientSocket = socket(servInfo->ai_family, servInfo->ai_socktype, servInfo->ai_protocol) ; if (clientSocket < 0) { mexErrMsgTxt("socket()") ; } while (numAttemptsLeft -- > 0) { status = sendto(clientSocket, key, strlen(key), 0, servInfo->ai_addr, sizeof(struct sockaddr_in)) ; status = recvfromTimeOut(clientSocket, 5, 0) ; if (status < 0) break ; if (status == 0) { mexPrintf("Resending request due to timeout (%d left)\n", numAttemptsLeft) ; continue ; } answerRecvLength = recvfrom(clientSocket, answer, answerLength, 0, servInfo->ai_addr, &fromLength) ; break ; /* mexPrintf("answ %d: '%s'\n", answerRecvLength, answer) ; */ } close(clientSocket) ; out[OUT_GO] = mxCreateLogicalScalar(strcmp(answer, "stop") != 0) ; } freeaddrinfo(servInfo) ; }
int discoverDevice(EthernetDeviceInfo *device_info, uint16_t productID) { EthernetDeviceInfo device; // a MCC device that responded struct sockaddr_in sendaddr; struct sockaddr_in recvaddr; struct sockaddr_in remoteaddr; int sock; int broadcast; unsigned char msg[64]; bool finished = false; int nfound = 0; // number of matched devices found socklen_t remoteaddrSize; int BytesReceived; // create the socket if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("discoverDevice: Error in creating socket"); return -1; } // set the broadcast option broadcast = 1; if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0) { perror("discoverDevice: Error setting socket options"); close(sock); return -1; } // set up the send and receive addresses memset(&sendaddr, 0, sizeof(sendaddr)); sendaddr.sin_family = AF_INET; sendaddr.sin_addr.s_addr = INADDR_BROADCAST; sendaddr.sin_port = htons(DISCOVER_PORT); memset(&recvaddr, 0, sizeof(recvaddr)); recvaddr.sin_family = AF_INET; recvaddr.sin_addr.s_addr = INADDR_ANY; recvaddr.sin_port = htons(DISCOVER_PORT); // bind the socket for receive if (bind(sock, (struct sockaddr*)&recvaddr, sizeof(recvaddr)) < 0) { perror("discoverDevice: Error binding port"); close(sock); return -1; } // send a broadcast discover datagram msg[0] = 'D'; if (sendto(sock, msg, 1, 0, (struct sockaddr*)&sendaddr, sizeof(sendaddr)) != 1) { perror("discoverDevice: sendto failed"); close(sock); return -1; } // look for replies (including the original broadcast) while (!finished) { switch (recvfromTimeOut(sock, 1, 0)) { case 0: // timed out finished = true; break; case -1: // error printf("Error from recvfromTimeOut\n"); finished = true; close(sock); return -1; break; default: // got a reply remoteaddrSize = sizeof(remoteaddr); BytesReceived = recvfrom(sock, msg, 64, 0, (struct sockaddr*)&remoteaddr, &remoteaddrSize); if ((BytesReceived == 64) && (msg[0] == 'D')) { memcpy(device.MAC, &msg[1], 6); memcpy(&device.ProductID, &msg[7], 2); memcpy(&device.FirmwareVersion, &msg[9], 2); memcpy(device.NetBIOS_Name, &msg[11], 16); memcpy(&device.CommandPort, &msg[27], 2); memcpy(&device.Status, &msg[33], 2); memcpy(&device.RemoteHost.sin_addr, &msg[35], 4); memcpy(&device.BootloaderVersion, &msg[39], 2); memcpy(&device.Address, &remoteaddr, sizeof(remoteaddr)); if (device.ProductID == productID) { // check for match memcpy(device_info, &device, sizeof(EthernetDeviceInfo)); nfound++; } } break; } } close(sock); return nfound; }
int openDevice(uint32_t addr, uint32_t connectCode) { int sock; struct sockaddr_in sendaddr; unsigned char msg[64]; int bytesReceived; // open the UDP socket if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("openDevice: Error creating socket."); return -1; } // set up the send address memset(&sendaddr, 0, sizeof(sendaddr)); sendaddr.sin_family = AF_INET; sendaddr.sin_addr.s_addr = addr; sendaddr.sin_port = htons(DISCOVER_PORT); if (connect(sock, (const struct sockaddr*) &sendaddr, sizeof(sendaddr)) < 0) { perror("openDevice: error in connect."); close(sock); return -1; } // send the connect message msg[0] = 'C'; memcpy(&msg[1], &connectCode, 4); if (send(sock, msg, 5, 0) < 0) { perror("openDevice: Error in send."); close(sock); return -1; } // look for a reply switch (recvfromTimeOut(sock, 1, 0)) { case 0: // timed out case -1: // error close (sock); return -1; break; default: // got a reply bytesReceived = recv(sock, msg, 64, 0); if ((bytesReceived == 2) && (msg[0] = 'C') && (msg[1] == 0)) { break; } else { close(sock); return -1; } break; } close(sock); // finished with the UDP portion if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { perror("openDevice: error creating TCP socket."); return -1; } // set up the send address memset(&sendaddr, 0, sizeof(sendaddr)); sendaddr.sin_family = AF_INET; sendaddr.sin_addr.s_addr = addr; sendaddr.sin_port = htons(COMMAND_PORT); // create a tcp connection if ((connect(sock, (const struct sockaddr*) &sendaddr, sizeof(sendaddr))) < 0) { perror("openDevice: can not connect to device."); close(sock); return -1; } return sock; }