static boolean getOurAck(struct rudp *ru, struct timeval *startTv, struct sockaddr_in *sai) /* Wait for acknowledgement to the message we just sent. * The set should be zeroed out. Only wait for up to * ru->timeOut microseconds. Prints a message and returns FALSE * if there's a problem. */ { struct rudpHeader head; int readSize; int timeOut = ru->timeOut; struct sockaddr_in retFrom; unsigned int retFromSize = sizeof(retFrom); for (;;) { /* Set up select with our time out. */ int dt; struct timeval tv; if (readReadyWait(ru->socket, timeOut)) { /* Read message and if it's our ack return true. */ readSize = recvfrom(ru->socket, &head, sizeof(head), 0, (struct sockaddr*)&retFrom, &retFromSize); if (readSize >= sizeof(head) && head.type == rudpAck && head.id == ru->lastId) { if ((sai->sin_addr.s_addr==retFrom.sin_addr.s_addr) && (sai->sin_port==retFrom.sin_port)) { gettimeofday(&tv, NULL); dt = timeDiff(startTv, &tv); rudpAddRoundTripTime(ru, dt); return TRUE; } else { char retFromDottedQuad[17]; char saiDottedQuad[17]; internetIpToDottedQuad(ntohl(retFrom.sin_addr.s_addr), retFromDottedQuad); internetIpToDottedQuad(ntohl(sai->sin_addr.s_addr), saiDottedQuad); warn("rudp: discarding mistaken ack from %s:%d by confirming recipient ip:port %s:%d" , retFromDottedQuad, retFrom.sin_port , saiDottedQuad, sai->sin_port ); } } } /* If we got to here then we did get a message, but it's not our * ack. We ignore the message and loop around again, but update * our timeout so that we won't keep getting other people's messages * forever. */ gettimeofday(&tv, NULL); timeOut = ru->timeOut - timeDiff(startTv, &tv); if (timeOut <= 0) return FALSE; } }
void doRun(char *line, struct sockaddr_in *hubIp) /* Execute command. */ { char *jobMessage = cloneString(line); static char *args[1024]; int argCount; char hubDottedQuad[17]; nextRandom(); if (line == NULL) warn("Executing nothing..."); else if (!internetIpToDottedQuad(ntohl(hubIp->sin_addr.s_addr), hubDottedQuad)) warn("Can't convert ipToDottedQuad"); else { struct runJobMessage rjm; if (parseRunJobMessage(line, &rjm)) { int jobId = atoi(rjm.jobIdString); if (findRunningJob(jobId) == NULL && findFinishedJob(jobId) == NULL) { if (busyProcs < maxProcs) { int childPid; argCount = chopLine(rjm.command, args); if (argCount >= ArraySize(args)) warn("Too many arguments to run"); else { args[argCount] = NULL; if ((childPid = forkOrDie()) == 0) { /* Do JOB_ID substitutions */ struct subText *st = subTextNew("$JOB_ID", rjm.jobIdString); int i; rjm.in = subTextString(st, rjm.in); rjm.out = subTextString(st, rjm.out); rjm.err = subTextString(st, rjm.err); for (i=0; i<argCount; ++i) args[i] = subTextString(st, args[i]); execProc(hubDottedQuad, rjm.jobIdString, rjm.reserved, rjm.user, rjm.dir, rjm.in, rjm.out, rjm.err, rjm.ram, args[0], args); exit(0); } else { struct job *job; AllocVar(job); job->jobId = atoi(rjm.jobIdString); job->pid = childPid; job->startMessage = jobMessage; jobMessage = NULL; /* No longer own memory. */ job->node = dlAddValTail(jobsRunning, job); ++busyProcs; } } } else { warn("Trying to run when busy."); } } else { warn("Duplicate run-job %d\n", jobId); } } } freez(&jobMessage); }
int rudpReceiveTimeOut(struct rudp *ru, void *messageBuf, int bufSize, struct sockaddr_in *retFrom, int timeOut) /* Read message into buffer of given size. Returns actual size read on * success. On failure prints a warning, sets errno, and returns -1. * Also returns ip address of message source. If timeOut is nonzero, * it represents the timeout in milliseconds. It will set errno to * ETIMEDOUT in this case.*/ { char inBuf[udpEthMaxSize]; struct rudpHeader *head = (struct rudpHeader *)inBuf; struct rudpHeader ackHead; struct sockaddr_in sai; socklen_t saiSize = sizeof(sai); int readSize, err; assert(bufSize <= rudpMaxSize); ru->receiveCount += 1; for (;;) { if (timeOut != 0) { if (!readReadyWait(ru->socket, timeOut)) { warn("rudpReceive timed out\n"); errno = ETIMEDOUT; return -1; } } readSize = recvfrom(ru->socket, inBuf, sizeof(inBuf), 0, (struct sockaddr*)&sai, &saiSize); if (retFrom != NULL) *retFrom = sai; if (readSize < 0) { if (errno == EINTR) continue; warn("recvfrom error: %s", strerror(errno)); ru->failCount += 1; return readSize; } if (readSize < sizeof(*head)) { warn("rudpRecieve truncated message"); continue; } if (head->type != rudpData) { if (head->type != rudpAck) warn("skipping non-data message %d in rudpReceive", head->type); continue; } ackHead = *head; ackHead.type = rudpAck; err = sendto(ru->socket, &ackHead, sizeof(ackHead), 0, (struct sockaddr *)&sai, sizeof(sai)); if (err < 0) { warn("problem sending ack in rudpRecieve: %s", strerror(errno)); } readSize -= sizeof(*head); if (readSize > bufSize) { warn("read more bytes than have room for in rudpReceive"); readSize = bufSize; } memcpy(messageBuf, head+1, readSize); /* check for duplicate packet */ if (!ru->recvHash) { /* take advantage of new auto-expanding hashes */ ru->recvHash = newHashExt(4, FALSE); /* do not use local mem in hash */ ru->recvList = newDlList(); ru->recvCount = 0; } char hashKey[64]; char saiDottedQuad[17]; internetIpToDottedQuad(ntohl(sai.sin_addr.s_addr), saiDottedQuad); safef(hashKey, sizeof(hashKey), "%s-%d-%d-%d" , saiDottedQuad , head->pid , head->connId , head->id ); if (hashLookup(ru->recvHash, hashKey)) { warn("duplicate packet filtered out: %s", hashKey); continue; } long now = time(NULL); struct packetSeen *p; AllocVar(p); AllocVar(p->node); p->node->val = p; p->recvHashKey = hashStoreName(ru->recvHash, hashKey); p->lastChecked = now; dlAddTail(ru->recvList, p->node); ++ru->recvCount; sweepOutOldPacketsSeen(ru, now); ru->lastIdReceived = head->id; break; } return readSize; }