/* * We end up here due to a osegw_receive, osegw_receive_w_tmo or * osegw_init_async_receive. While we are waiting for a signal, * we must be able to handle "pings" and osegw_cancel_async_receive * from the client. */ int OseGW_PLT_ReceiveRequest_cbk(int skt, int len, char *payload, struct ClientInfo *cinfo) { struct OseGW_ReceiveRequest *req; struct OseGW_TransportHdr thdr; union LINX_SIGNAL *sig; LINX_SIGSELECT *sigsel; int nfds, status, size, linx_skt, sigsel_len; fd_set rfds; struct timeval tv0, tv, *tvp; unsigned int tmo; void *buf; linx_skt = linx_get_descriptor(cinfo->linx); req = (struct OseGW_ReceiveRequest *)payload; sigsel_len = ntohl(req->sigsel_len); buf = NULL; /* 0. This may be a osegw_cancel_async_receive... */ if (sigsel_len == 0) { sig = NULL; size = 0; goto out; } /* 1. Setup signal filter that should be used while polling... */ sigsel = copy_sigselect(req); if (sigsel == NULL) goto e_exit; if (set_sigselect(linx_skt, sigsel) == -1) goto e_exit; /* 2. Setup time-out... */ tmo = ntohl(req->timeout); if (tmo != (unsigned int)~0) { tvp = msec_to_timeval(tmo, &tv); if (gettimeofday(&tv0, NULL) == -1) goto e_exit; } else tvp = NULL; /* Infinite */ again: /* 3. Setup descriptors... */ FD_ZERO(&rfds); FD_SET(linx_skt, &rfds); /* LINX socket */ FD_SET(skt, &rfds); /* TCP socket */ nfds = linx_skt > skt ? linx_skt : skt; /* 4. Wait for a signal, ping or osegw_cancel_async_receive */ status = select(nfds + 1, &rfds, NULL, NULL, tvp); if (status == -1) goto e_exit; if (status == 0) { /* osegw_receive_w_tmo has timed out */ sig = NULL; size = 0; goto out; } if (FD_ISSET(linx_skt, &rfds)) { /* A signal that matches the signal filter is available */ status = linx_receive(cinfo->linx, &sig, sigsel); if (status == -1) goto e_exit; size = linx_sigsize(cinfo->linx, &sig) - sizeof(SIGSELECT); goto out; } if (FD_ISSET(cinfo->sd, &rfds)) { /* Get command */ buf = get_command(skt, &thdr); if (buf == NULL) goto e_exit; switch (thdr.payload_type) { case OseGW_PLT_InterfaceRequest: status = OseGW_PLT_InterfaceRequest_cbk(skt, thdr.payload_len, buf, cinfo); if (status == -1) goto e_exit; /* Compensate for the time spent in select */ if (tvp != NULL) recalc_tmo(tmo, &tv0, &tv); goto again; break; case OseGW_PLT_ReceiveRequest: req = (struct OseGW_ReceiveRequest *)buf; sigsel_len = ntohl(req->sigsel_len); if (sigsel_len != 0) goto e_exit; /* Only cancel async receive is allowed */ sig = NULL; size = 0; goto out; break; default: syslog(LOG_INFO, "Gateway protocol violation detected, " "got type %d while in a receive", thdr.payload_type); goto e_exit; break; } } out: free(buf); free(sigsel); return OseGW_PLT_ReceiveReply_cbk(skt, size, (char *)sig, cinfo); e_exit: free(buf); free(sigsel); return -1; }
static void test_without_linxlib(LINX_SPID client, LINX * linx) { int len, sig_len; struct sockaddr_linx to; socklen_t socklen; int sd = linx_get_descriptor(linx); size_t msg_size = 65536; union LINX_SIGNAL *sig = malloc(msg_size); if (sig == NULL) { ERR("Failed to allocate memory"); exit(1); } socklen = sizeof(struct sockaddr_linx); to.family = AF_LINX; to.spid = LINX_ILLEGAL_SPID; for (;;) { len = sig_len = recvfrom(sd, sig, msg_size, 0, (struct sockaddr *)(void *)&to, &socklen); if (unlikely(len <= 0)) { ERR("Failed to receive a signal(%d, %d)\n", len, errno); continue; } if (unlikely(to.spid != client)) { WARN("Ignoring signal from spid %#x since it is" " not %#x", to.spid, client); continue; } switch (sig->sigNo) { case ECHO_SIG: TRACE(1, "Sending echo"); len = sendto(sd, sig, len, 0, (struct sockaddr *)(void *)&to, socklen); if (unlikely(sig_len != len)) { ERR("sendto returned: %d when asked " "for: %d", len, sig_len); } if (unlikely(len <= 0)) { ERR("Failed to send the echo signal " "(%d, %s)\n", len, strerror(errno)); } break; case TERMINATE_REQ: TRACE(1, "Terminating"); free(sig); linx_close(linx); return; case ATTACH_TEST_REQ: len = sendto(sd, sig, len, 0, (struct sockaddr *)(void *)&to, socklen); if (unlikely(sig_len != len)) { ERR("sendto returned: %d when asked " "for: %d", len, sig_len); } if (unlikely(len <= 0)) { ERR("Failed to send the echo signal " "(%d, %s)\n", len, strerror(errno)); } linx_close(linx); return; case BURST_REQ: { uint32_t sigCnt = ntohl(sig->burstReq.n); uint32_t reply_size = ntohl(sig->burstReq.reply_size); LINX_SIGSELECT reply_sigNo = ntohl(sig->burstReq.reply_sigNo); /* Allocate all signals before sending then to * make the send loop as tight as possible */ sig->burstSig.sigNo = reply_sigNo; while (sigCnt--) { len = sendto(sd, sig, reply_size, 0, (struct sockaddr *)(void *)&to, socklen); if (unlikely (reply_size != (uint32_t) len)) { ERR("sendto returned: %d when " "asked for: %d", len, reply_size); } if (unlikely(len <= 0)) { ERR("Failed to send the echo " "signal (%d, %s)\n", len, strerror(errno)); } } break; } default: WARN("Ignoring unknown signal %ud", sig->sigNo); } } free(sig); }