/** * Indicates if a particular multicast LDM sender is running. * * @pre Multicast LDM sender PID map is locked for writing. * @param[in] feedtype Feed-type of multicast group. * @param[out] pid Process ID of the multicast LDM sender. * @param[out] port Port number of the VCMTP TCP server. * @retval 0 The multicast LDM sender associated with the given * multicast group is running. `*pid` and `*port` are * set. * @retval LDM7_NOENT No such process. * @retval LDM7_SYSTEM System error. `log_start()` called. */ static Ldm7Status mlsm_isRunning( const feedtypet feedtype, pid_t* const pid, unsigned short* const port) { pid_t msmPid; unsigned short msmPort; int status = msm_get(feedtype, &msmPid, &msmPort); if (status == 0) { if (kill(msmPid, 0) == 0) { /* Can signal the process */ *pid = msmPid; *port = msmPort; } else { /* Can't signal the process */ uwarn("According to my information, the PID of the multicast LDM " "sender associated with feed-type %s is %d -- but that " "process can't be signaled by this process. I'll assume " "the relevant multicast LDM sender is not running.", s_feedtypet(feedtype), msmPid); (void)msm_remove(msmPid); // don't care if it exists or not status = LDM7_NOENT; } } return status; }
static usbh_baseclassdriver_t *_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) { int i; USBHCustomDriver *custp; (void)dev; if (_usbh_match_vid_pid(dev, 0xABCD, 0x0123) != HAL_SUCCESS) return NULL; const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t *)descriptor; /* alloc driver */ for (i = 0; i < USBH_CUSTOM_CLASS_MAX_INSTANCES; i++) { if (USBHCUSTOMD[i].dev == NULL) { custp = &USBHCUSTOMD[i]; goto alloc_ok; } } uwarn("Can't alloc CUSTOM driver"); /* can't alloc */ return NULL; alloc_ok: /* initialize the driver's variables */ custp->ifnum = ifdesc->bInterfaceNumber; /* parse the configuration descriptor */ if_iterator_t iif; generic_iterator_t iep; iif.iad = 0; iif.curr = descriptor; iif.rem = rem; for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) { const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep); if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_INT)) { /* ... */ } else { uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bmAttributes); } } custp->state = USBHCUSTOM_STATE_ACTIVE; return (usbh_baseclassdriver_t *)custp; }
static msd_result_t _scsi_perform_transaction(USBHMassStorageLUNDriver *lunp, msd_transaction_t *transaction, void *data) { msd_bot_result_t res; res = _msd_bot_transaction(transaction, lunp, data); if (res != MSD_BOTRESULT_OK) { return (msd_result_t)res; } if (transaction->csw_status == CSW_STATUS_FAILED) { if (transaction->cbw->CBWCB[0] != SCSI_CMD_REQUEST_SENSE) { /* do auto-sense (except for SCSI_CMD_REQUEST_SENSE!) */ uwarn("\tMSD: Command failed, auto-sense"); USBH_DEFINE_BUFFER(scsi_sense_response_t sense); if (scsi_requestsense(lunp, &sense) == MSD_RESULT_OK) { uwarnf("\tMSD: REQUEST SENSE: Sense key=%x, ASC=%02x, ASCQ=%02x", sense.byte[2] & 0xf, sense.byte[12], sense.byte[13]); } } return MSD_RESULT_FAILED; } return MSD_RESULT_OK; }
/* * Create a TCP socket, bind it to a port, call 'listen' (we are a * server), and inform the portmap (rpcbind) service. Does _not_ create * an RPC SVCXPRT or do the xprt_register() or svc_fds() stuff. * * Arguments: * sockp Pointer to socket (file) descriptor. Set on and only on * success. * localIpAddr The IP address, in network byte order, of the * local interface to use. May be htonl(INADDR_ANY). * localPort The number of the local port on which the LDM server * should listen. * Returns: * 0 Success. * EACCES The process doesn't have appropriate privileges. * EADDRINUSE The local address is already in use. * EADDRNOTAVAIL The specified address is not available from the local * machine. * EAFNOSUPPORT The system doesn't support IP. * EMFILE No more file descriptors are available for this process. * ENFILE No more file descriptors are available for the system. * ENOBUFS Insufficient resources were available in the system. * ENOMEM Insufficient memory was available. * ENOSR There were insufficient STREAMS resources available. * EOPNOTSUPP The socket protocol does not support listen(). * EPROTONOSUPPORT The system doesn't support TCP. */ static int create_ldm_tcp_svc( int* sockp, in_addr_t localIpAddr, unsigned localPort) { int error = 0; /* success */ int sock; /* * Get a TCP socket. */ udebug("create_ldm_tcp_svc(): Getting TCP socket"); sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock < 0) { error = errno; serror("Couldn't get socket for server"); } else { unsigned short port = (unsigned short) localPort; struct sockaddr_in addr; socklen_t len = sizeof(addr); /* * Eliminate problem with EADDRINUSE for reserved socket. * We get this if an upstream data source hasn't tried to * write on the other end and we are in FIN_WAIT_2 */ udebug("create_ldm_tcp_svc(): Eliminating EADDRINUSE problem."); { int on = 1; (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); } (void) memset(&addr, 0, len); addr.sin_family = AF_INET; addr.sin_addr.s_addr = localIpAddr; addr.sin_port = (short) htons((short) port); /* * If privilege available, set it so we can bind to the port for LDM * services. Also needed for the pmap_set() call. */ udebug("create_ldm_tcp_svc(): Getting root privs"); rootpriv(); udebug("create_ldm_tcp_svc(): Binding socket"); if (bind(sock, (struct sockaddr *) &addr, len) < 0) { error = errno; serror("Couldn't obtain local address %s:%u for server", inet_ntoa(addr.sin_addr), (unsigned) port); if (error == EACCES) { error = 0; addr.sin_port = 0; /* let system assign port */ if (bind(sock, (struct sockaddr *) &addr, len) < 0) { error = errno; serror("Couldn't obtain local address %s:* for server", inet_ntoa(addr.sin_addr)); } } /* requested port is reserved */ } /* couldn't bind to requested port */ if (!error) { /* * Get the local address associated with the bound socket. */ udebug("create_ldm_tcp_svc(): Calling getsockname()"); if (getsockname(sock, (struct sockaddr *) &addr, &len) < 0) { error = errno; serror("Couldn't get local address of server's socket"); } else { port = (short) ntohs((short) addr.sin_port); unotice("Using local address %s:%u", inet_ntoa(addr.sin_addr), (unsigned) port); udebug("create_ldm_tcp_svc(): Calling listen()"); if (listen(sock, 32) != 0) { error = errno; serror("Couldn't listen() on server's socket"); } else { /* * Register with the portmapper if it's running. The * check to see if it's running is made because on a * FreeBSD 4.7-STABLE system, a pmap_set() call takes * one minute even if the portmapper isn't running. */ udebug("create_ldm_tcp_svc(): Checking portmapper"); if (local_portmapper_running()) { udebug("create_ldm_tcp_svc(): Registering"); if (pmap_set(LDMPROG, 6, IPPROTO_TCP, port) == 0) { uwarn("Can't register TCP service %lu on " "port %u", LDMPROG, (unsigned) port); uwarn("Downstream LDMs won't be able to " "connect via the RPC portmapper daemon " "(rpcbind(8), portmap(8), etc.)"); } else { portIsMapped = 1; (void) pmap_set(LDMPROG, 5, IPPROTO_TCP, port); } } /* a local portmapper is running */ /* * Done with the need for privilege. */ udebug("create_ldm_tcp_svc(): Releasing root privs"); unpriv(); *sockp = sock; } /* listen() success */ } /* getsockname() success */ } /* "sock" is bound to local address */ if (error) (void) close(sock); } /* "sock" is open */ return error; }
hiya_reply_t* hiya_6_svc( prod_class_t *offered, struct svc_req *rqstp) { const char* const pqfname = getQueuePath(); static hiya_reply_t reply; SVCXPRT * const xprt = rqstp->rq_xprt; struct sockaddr_in *upAddr = (struct sockaddr_in*) svc_getcaller(xprt); const char *upName = hostbyaddr(upAddr); int error; int isPrimary; unsigned int maxHereis; static prod_class_t *accept; /* * Open the product-queue for writing. It will be closed by cleanup() * during process termination. */ if (pq) { (void) pq_close(pq); pq = NULL; } error = pq_open(pqfname, PQ_DEFAULT, &pq); if (error) { err_log_and_free(ERR_NEW2(error, NULL, "Couldn't open product-queue \"%s\" for writing: %s", pqfname, PQ_CORRUPT == error ? "The product-queue is inconsistent" : strerror(error)), ERR_FAILURE); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } /* else */ error = down6_init(upName, upAddr, pqfname, pq); if (error) { uerror("Couldn't initialize downstream LDM"); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } else { uinfo("Downstream LDM initialized"); } /* * The previous "accept" is freed here -- rather than freeing the * soon-to-be-allocated "accept" at the end of its block -- because it can * be used in the reply. */ if (accept) { free_prod_class(accept); /* NULL safe */ accept = NULL; } error = lcf_reduceToAcceptable(upName, inet_ntoa(upAddr->sin_addr), offered, &accept, &isPrimary); maxHereis = isPrimary ? UINT_MAX : 0; if (error) { serror("Couldn't validate HIYA"); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } else { if (ulogIsDebug()) udebug("intersection: %s", s_prod_class(NULL, 0, accept)); if (accept->psa.psa_len == 0) { uwarn("Empty intersection of HIYA offer from %s (%s) and ACCEPT " "entries", upName, s_prod_class(NULL, 0, offered)); svcerr_weakauth(xprt); svc_destroy(xprt); exit(0); } else { error = down6_set_prod_class(accept); if (error) { if (DOWN6_SYSTEM_ERROR == error) { serror("Couldn't set product class: %s", s_prod_class(NULL, 0, accept)); } else { uerror("Couldn't set product class: %s", s_prod_class(NULL, 0, accept)); } svcerr_systemerr(xprt); svc_destroy(xprt); exit(EXIT_FAILURE); } /* else */ if (clss_eq(offered, accept)) { unotice("hiya6: %s", s_prod_class(NULL, 0, offered)); reply.code = OK; reply.hiya_reply_t_u.max_hereis = maxHereis; } else { if (ulogIsVerbose()) { char off[512]; char acc[512]; (void) s_prod_class(off, sizeof(off), offered), (void) s_prod_class( acc, sizeof(acc), accept); uinfo("hiya6: RECLASS: %s -> %s", off, acc); } reply.code = RECLASS; reply.hiya_reply_t_u.feedPar.prod_class = accept; reply.hiya_reply_t_u.feedPar.max_hereis = maxHereis; } } /* product-intersection != empty set */ } /* successful acl_check_hiya() */ return &reply; }
/* returns 0 or errno on error */ int pbuf_flush( pbuf* buf, int block, /* bool_t */ unsigned int timeo, /* N.B. Not a struct timeval */ const char* const id) /* destination identifier */ { size_t len = (size_t)(buf->ptr - buf->base); int changed = 0; int nwrote = 0; int status = ENOERR; /* success */ int tmpErrno; time_t start; time_t duration; udebug(" pbuf_flush fd %d %6d %s", buf->pfd, len, block ? "block" : "" ); if(len == 0) return 0; /* nothing to do */ /* else */ (void)time(&start); if(block) changed = clr_fd_nonblock(buf->pfd); if(block && timeo != 0) /* (timeo == 0) => don't set alarm */ SET_ALARM(timeo, flush_timeo); nwrote = (int) write(buf->pfd, buf->base, len); tmpErrno = errno; /* CLR_ALRM() can change "errno" */ if(block && timeo != 0) CLR_ALRM(); if(nwrote == -1) { if((tmpErrno == EAGAIN) && (!block)) { udebug(" pbuf_flush: EAGAIN on %d bytes", len); nwrote = 0; } else { status = tmpErrno; serror(NULL == id ? "pbuf_flush(): fd=%d" : "pbuf_flush(): fd=%d, cmd=(%s)", buf->pfd, id); } } else if(nwrote == len) { /* wrote the whole buffer */ udebug(" pbuf_flush: wrote %d bytes", nwrote); buf->ptr = buf->base; len = 0; } else if(nwrote > 0) { /* partial write, just shift the buffer by the amount written */ udebug(" pbuf_flush: partial write %d of %d bytes", nwrote, len); len -= nwrote; /* could be an overlapping copy */ memmove(buf->base, buf->base + nwrote, len); buf->ptr = buf->base +len; } if(changed) set_fd_nonblock(buf->pfd); duration = time(NULL) - start; if(duration > 5) uwarn(id == NULL ? "pbuf_flush(): write(%d,,%d) to decoder took %lu s" : "pbuf_flush(): write(%d,,%d) to decoder took %lu s: %s", buf->pfd, nwrote, (unsigned long)duration, id); return status; flush_timeo: if(changed) set_fd_nonblock(buf->pfd); uerror(id == NULL ? "pbuf_flush(): write(%d,,%lu) to decoder timed-out (%lu s)" : "pbuf_flush(): write(%d,,%lu) to decoder timed-out (%lu s): %s", buf->pfd, (unsigned long)len, (unsigned long)(time(NULL) - start), id); return EAGAIN; }
/** * Executes a product-maker. * * This function is thread-compatible but not thread-safe. * * @retval (void*)0 The FIFO was closed. * @retval (void*)1 Usage failure. \c log_start() called. * @retval (void*)2 O/S failure. \c log_start() called. * @retval (void*)-1 Retransmission failure. \c log_start() called. */ void* pmStart( void* const arg) /**< [in/out] Pointer to the * product-maker to be executed */ { ProductMaker* const productMaker = (ProductMaker*)arg; int status; Fifo* const fifo = productMaker->fifo; unsigned char* buf = productMaker->buf; sbn_struct* sbn = &productMaker->sbn; pdh_struct* pdh = &productMaker->pdh; psh_struct* psh = &productMaker->psh; pdb_struct* pdb = &productMaker->pdb; ccb_struct* ccb = &productMaker->ccb; unsigned long last_sbn_seqno; unsigned long last_sbn_runno = ULONG_MAX; int PNGINIT = 0; char* memheap = NULL; MD5_CTX* md5ctxp = productMaker->md5ctxp; int logResync = 1; prodstore prod; #ifdef RETRANS_SUPPORT long cpio_addr_tmp; int cpio_fd_tmp; /* char transfer_type[10]={0};*/ int retrans_val,idx; long retrans_tbl_size; time_t orig_arrive_time; int new_key; /* shm key */ ACQ_TABLE *acq_tbl = NULL; long num_prod_discards=0; int save_prod = 1; int discard_prod = 0; long proc_orig_prod_seqno_last_save=0; #endif prod.head = NULL; prod.tail = NULL; /*** For Retranmission Purpose ***/ #ifdef RETRANS_SUPPORT if (ulogIsDebug()) udebug(" retrans_xmit_enable = %d transfer_type = %s sbn_channel_name=%s \n",retrans_xmit_enable,transfer_type,sbn_channel_name); if((retrans_xmit_enable == OPTION_ENABLE) && (!strcmp(transfer_type,"MHS") || !strcmp(transfer_type,"mhs"))){ idx = get_cpio_addr(mcastAddr); if( idx >= 0 && idx < NUM_CPIO_ENTRIES){ global_cpio_fd = cpio_tbl[idx].cpio_fd; global_cpio_addr = cpio_tbl[idx].cpio_addr; if (ulogIsDebug()) udebug("Global cpio_addr = 0x%x Global cpio_fd = %d \n",global_cpio_addr,global_cpio_fd); }else{ uerror("Invalid multicast address provided"); return (void*)-1; } retrans_tbl_size = sizeof(PROD_RETRANS_TABLE); /** Modified to setup retrans table on per channel basis - Sathya - 14-Mar'2013 **/ retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * GET_RETRANS_CHANNEL_ENTRIES(sbn_type)); /**** retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * DEFAULT_RETRANS_ENTRIES_NMC); retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * DEFAULT_RETRANS_ENTRIES_NMC1); retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * DEFAULT_RETRANS_ENTRIES_NMC2); retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * DEFAULT_RETRANS_ENTRIES_NMC3); retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * DEFAULT_RETRANS_ENTRIES_GOES_EAST); retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * DEFAULT_RETRANS_ENTRIES_NOAAPORT_OPT); ****/ p_prod_retrans_table = (PROD_RETRANS_TABLE *) malloc (retrans_tbl_size); if(p_prod_retrans_table == NULL){ uerror("Unable to allocate memory for retrans table..Quitting.\n"); return (void*)-1; } if( init_retrans(&p_prod_retrans_table) < 0 ){ uerror("Error in initializing retrans table \n"); if(p_prod_retrans_table) free(p_prod_retrans_table); return (void*)-1; } GET_SHMPTR(global_acq_tbl,ACQ_TABLE,ACQ_TABLE_SHMKEY,DEBUGGETSHM); if (ulogIsDebug()) udebug("Global acquisition table = 0x%x cpio_fd = %d \n",global_acq_tbl,global_cpio_fd); acq_tbl = &global_acq_tbl[global_cpio_fd]; if (ulogIsDebug()) udebug("Obtained acquisition table = 0x%x \n",acq_tbl); /* ACQ_TABLE already initialized in acq_ldm_getshm */ /* if(init_acq_table(acq_tbl) < 0){ uerror("Unable to initialize acq table\n"); exit(-1); } */ buff_hdr = (BUFF_HDR *) malloc(sizeof(BUFF_HDR)); if(init_buff_hdr(buff_hdr) < 0){ uerror("Unalbe to initialize buffer header \n"); if(acq_tbl) free(acq_tbl); if(p_prod_retrans_table) free(p_prod_retrans_table); return (void*)-1; } acq_tbl->pid = getpid(); acq_tbl->link_id = global_cpio_fd; acq_tbl->link_addr = global_cpio_addr; if(ulogIsVerbose()){ uinfo("Initialized acq_tbl = 0x%x & buff_hdr = 0x%x pid = %d \n",acq_tbl,buff_hdr,acq_tbl->pid); uinfo("Global link id = %d Global link addr = %ld \n",acq_tbl->link_id,acq_tbl->link_addr); uinfo("acq_tbl->read_distrib_enable = 0x%x \n",acq_tbl->read_distrib_enable); } } /*** For Retranmission Purpose ***/ #endif for (;;) { unsigned char b1; long IOFF; int NWSTG; int GOES; int PROD_COMPRESSED; size_t heapcount; size_t heapsize; char PROD_NAME[1024]; int dataoff; int datalen; datastore* pfrag; int nscan; int deflen; static const char* FOS_TRAILER = "\015\015\012\003"; int cnt; /* Look for first byte == 255 and a valid SBN checksum */ if ((status = fifoRead(fifo, buf, 1)) != 0) { if (3 == status) status = 0; break; } if ((b1 = (unsigned char)buf[0]) != 255) { if (logResync) { uinfo("Trying to resync %u", b1); logResync = 0; } continue; } logResync = 1; if (fifoRead(fifo, buf + 1, 15) != 0) { if (ulogIsDebug()) udebug("couldn't read 16 bytes for sbn"); continue; } while ((status = readsbn(buf, sbn)) != 0) { if (ulogIsDebug()) udebug("Not SBN start"); IOFF = 1; while ((IOFF < 16) && ((b1 = (unsigned char) buf[IOFF]) != 255)) IOFF++; if (IOFF > 15) { break; } else { int ch; for (ch = IOFF; ch < 16; ch++) buf[ch - IOFF] = buf[ch]; if (fifoRead(fifo, buf + 16 - IOFF, IOFF) != 0) { if (ulogIsDebug()) udebug("Couldn't read bytes for SBN, resync"); break; } } } if (status != 0) { if (ulogIsDebug()) udebug("SBN status continue"); continue; } IOFF = 0; if (fifoRead(fifo, buf + 16, 16) != 0) { if (ulogIsDebug()) udebug("error reading Product Definition Header"); continue; } #ifdef RETRANS_SUPPORT /* Update acq table stats - Begin */ if(retrans_xmit_enable == OPTION_ENABLE){ buff_hdr->read_channel_type = sbn->datastream; } /* Update acq table stats - End */ #endif if (ulogIsDebug()) udebug("***********************************************"); if (last_sbn_runno != sbn->runno) { last_sbn_runno = sbn->runno; } else { unsigned long delta = sbn->seqno - last_sbn_seqno; # define MAX_SEQNO 0xFFFFFFFFu if (0 == delta || MAX_SEQNO/2 < delta) { uwarn("Retrograde packet number: previous=%lu, latest=%lu, " "difference=%lu", last_sbn_seqno, sbn->seqno, 0 == delta ? 0ul : MAX_SEQNO - delta + 1); } else { if (1 != delta) { unsigned long gap = delta - 1; uwarn("Gap in packet sequence: %lu to %lu [skipped %lu]", last_sbn_seqno, sbn->seqno, gap); (void)pthread_mutex_lock(&productMaker->mutex); productMaker->nmissed += gap; (void)pthread_mutex_unlock(&productMaker->mutex); } (void)pthread_mutex_lock(&productMaker->mutex); productMaker->npackets++; (void)pthread_mutex_unlock(&productMaker->mutex); } /* non-retrograde packet number */ } /* "last_sbn_seqno" initialized */ last_sbn_seqno = sbn->seqno; if (ulogIsVerbose()) uinfo("SBN seqnumber %ld", sbn->seqno); if (ulogIsVerbose()) uinfo("SBN datastream %d command %d", sbn->datastream, sbn->command); if (ulogIsDebug()) udebug("SBN version %d length offset %d", sbn->version, sbn->len); if (((sbn->command != 3) && (sbn->command != 5)) || (sbn->version != 1)) { uerror("Unknown sbn command/version %d PUNT", sbn->command); continue; } switch (sbn->datastream) { case 5: /* nwstg */ case 6: /* nwtg2 */ case 7: /* polarsat */ case 8: /* NOAA Weather Wire Service (NWWS) */ case 9: case 10: case 11: case 12: /* GOES-R */ case 13: /* GOES-R */ NWSTG = 1; GOES = 0; break; case 1: /* GINI GOES */ case 2: /* GINI GOES */ case 4: /* OCONUS */ NWSTG = 0; GOES = 1; break; default: uerror("Unknown NOAAport channel %d PUNT", sbn->datastream); continue; } /* End of SBN version low 4 bits */ if (readpdh(buf + IOFF + sbn->len, pdh) == -1) { uerror("problem with pdh, PUNT"); continue; } if (pdh->len > 16) { if (fifoRead(fifo, buf + sbn->len + 16, pdh->len - 16) != 0) continue; } if (ulogIsDebug()) udebug("Product definition header version %d pdhlen %d", pdh->version, pdh->len); if (pdh->version != 1) { uerror("Error: PDH transfer type %u, PUNT", pdh->transtype); continue; } else if (ulogIsDebug()) { udebug("PDH transfer type %u", pdh->transtype); } if ((pdh->transtype & 8) > 0) uerror("Product transfer flag error %u", pdh->transtype); if ((pdh->transtype & 32) > 0) uerror("Product transfer flag error %u", pdh->transtype); if ((pdh->transtype & 16) > 0) { PROD_COMPRESSED = 1; if (ulogIsDebug()) udebug("Product transfer flag compressed %u", pdh->transtype); } else { PROD_COMPRESSED = 0; } if (ulogIsDebug()) udebug("header length %ld [pshlen = %d]", pdh->len + pdh->pshlen, pdh->pshlen); if (ulogIsDebug()) udebug("blocks per record %ld records per block %ld\n", pdh->blocks_per_record, pdh->records_per_block); if (ulogIsDebug()) udebug("product seqnumber %ld block number %ld data block size " "%ld", pdh->seqno, pdh->dbno, pdh->dbsize); /* Stop here if no psh */ if ((pdh->pshlen == 0) && (pdh->transtype == 0)) { IOFF = IOFF + sbn->len + pdh->len; continue; } #ifdef RETRANS_SUPPORT /** Update acquisition table statistics **/ if(retrans_xmit_enable == OPTION_ENABLE){ acq_tbl->read_tot_buff_read++; } #endif if (pdh->pshlen != 0) { if (fifoRead(fifo, buf + sbn->len + pdh->len, pdh->pshlen) != 0) { uerror("problem reading psh"); continue; } else { if (ulogIsDebug()) udebug("read psh %d", pdh->pshlen); } /* Timing block */ if (sbn->command == 5) { if (ulogIsDebug()) udebug("Timing block recieved %ld %ld\0", psh->olen, pdh->len); /* * Don't step on our psh of a product struct of prod in * progress. */ continue; } if (readpsh(buf + IOFF + sbn->len + pdh->len, psh) == -1) { uerror("problem with readpsh"); continue; } if (psh->olen != pdh->pshlen) { uerror("ERROR in calculation of psh len %ld %ld", psh->olen, pdh->len); continue; } if (ulogIsDebug()) udebug("len %ld", psh->olen); if (ulogIsDebug()) udebug("product header flag %d, version %d", psh->hflag, psh->version); if (ulogIsDebug()) udebug("prodspecific data length %ld", psh->psdl); if (ulogIsDebug()) udebug("bytes per record %ld", psh->bytes_per_record); if (ulogIsDebug()) udebug("Fragments = %ld category %d ptype %d code %d", psh->frags, psh->pcat, psh->ptype, psh->pcode); if (psh->frags < 0) uerror("check psh->frags %d", psh->frags); if (psh->origrunid != 0) uerror("original runid %d", psh->origrunid); if (ulogIsDebug()) udebug("next header offset %ld", psh->nhoff); if (ulogIsDebug()) udebug("original seq number %ld", psh->seqno); if (ulogIsDebug()) udebug("receive time %ld", psh->rectime); if (ulogIsDebug()) udebug("transmit time %ld", psh->transtime); if (ulogIsDebug()) udebug("run ID %ld", psh->runid); if (ulogIsDebug()) udebug("original run id %ld", psh->origrunid); #ifdef RETRANS_SUPPORT /* Update acq table stats - Begin */ if(retrans_xmit_enable == OPTION_ENABLE){ buff_hdr->buff_data_length = pdh->dbsize; if(pdh->dbno == 0) { /* Assume first block */ acq_tbl->proc_base_prod_type_last = psh->ptype; acq_tbl->proc_base_prod_cat_last = psh->pcat; acq_tbl->proc_base_prod_code_last = psh->pcode; acq_tbl->proc_prod_NCF_rcv_time = (time_t)psh->rectime; acq_tbl->proc_prod_NCF_xmit_time = (time_t)psh->transtime; if(psh->hflag & XFR_PROD_RETRANSMIT){ acq_tbl->proc_orig_prod_seqno_last = psh->seqno; acq_tbl->proc_orig_prod_run_id = psh->origrunid; if(ulogIsDebug()) udebug("ORIG SEQ# = %ld CURR SEQ#: %ld \n",acq_tbl->proc_orig_prod_seqno_last,pdh->seqno); }else{ acq_tbl->proc_orig_prod_seqno_last = 0; acq_tbl->proc_orig_prod_run_id = 0; } acq_tbl->proc_prod_run_id = psh->runid; buff_hdr->buff_datahdr_length = psh->psdl; time(&acq_tbl->proc_prod_start_time); acq_tbl->proc_tot_prods_handled++; }else{ buff_hdr->buff_datahdr_length = 0; } buff_hdr->proc_prod_seqno= pdh->seqno; buff_hdr->proc_blkno = pdh->dbno; buff_hdr->proc_sub_code = 0; buff_hdr->proc_prod_flag = pdh->transtype; acq_tbl->proc_base_channel_type_last = buff_hdr->read_channel_type; buff_hdr->proc_prod_type = acq_tbl->proc_base_prod_type_last; buff_hdr->proc_prod_code = acq_tbl->proc_base_prod_code_last; buff_hdr->proc_prod_cat = acq_tbl->proc_base_prod_cat_last; acq_tbl->proc_prod_bytes_read = buff_hdr->buff_data_length; /* Check prod_seqno for lost products */ if((buff_hdr->proc_prod_seqno - acq_tbl->proc_base_prod_seqno_last) != 1){ do_prod_lost(buff_hdr,acq_tbl); } retrans_val = prod_retrans_ck(acq_tbl, buff_hdr, &orig_arrive_time); log_buff[0] = '\0'; if((retrans_val == PROD_DUPLICATE_DISCARD) || ((retrans_val == PROD_DUPLICATE_MATCH) && (acq_tbl->proc_retransmit_ctl_flag & ENABLE_RETRANS_DUP_MATCH_DISCARD)) || ((retrans_val == PROD_DUPLICATE_NOMATCH) && (acq_tbl->proc_retransmit_ctl_flag & ENABLE_RETRANS_DUP_NOMATCH_DISCARD))){ /* Log product details and discard the product */ strcpy(log_buff,"DISCARD"); if(acq_tbl->proc_orig_prod_seqno_last != 0){ strcat(log_buff, "/RETRANS"); } log_prod_end(log_buff, acq_tbl->proc_orig_prod_seqno_last, buff_hdr->proc_prod_seqno,buff_hdr->proc_blkno, buff_hdr->proc_prod_code, acq_tbl->proc_prod_bytes_read,orig_arrive_time); save_prod = 0; acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno; /* Current prod discarded and continue with next */ /*continue; */ }else{ if(retrans_val == PROD_DUPLICATE_NOMATCH){ strcpy(log_buff,"SAVE RETRANS"); log_prod_end(log_buff, acq_tbl->proc_orig_prod_seqno_last, buff_hdr->proc_prod_seqno,buff_hdr->proc_blkno, buff_hdr->proc_prod_code, acq_tbl->proc_prod_bytes_read,acq_tbl->proc_prod_start_time); } } } #endif if (prod.head != NULL) { uerror("OOPS, start of new product [%ld ] with unfinished " "product %ld", pdh->seqno, prod.seqno); #ifdef RETRANS_SUPPORT /* Request retrans when prod is partially received but before completion */ /* if there is frame error and continue with different prod then, we need */ /* to abort the old prod and clear retrans table. */ if((retrans_xmit_enable == OPTION_ENABLE) /*&& (pdh->dbno != 0)*/){ acq_tbl->proc_acqtab_prodseq_errs++; if(proc_orig_prod_seqno_last_save != acq_tbl->proc_orig_prod_seqno_last){ /* Clear retrans table for the orig prod if the previous prod is retrans */ /* of original prod */ prod_retrans_abort_entry(acq_tbl, proc_orig_prod_seqno_last_save, RETRANS_RQST_CAUSE_RCV_ERR); } prod_retrans_abort_entry(acq_tbl, prod.seqno, RETRANS_RQST_CAUSE_RCV_ERR); /* Update Statistics */ acq_tbl->proc_tot_prods_lost_errs++; /* For now, generate retrans request only for non-imagery products */ if(!((buff_hdr->proc_prod_cat == PROD_CAT_IMAGE) && (PROD_TYPE_NESDIS_HDR_TRUE(buff_hdr->proc_prod_type)))){ generate_retrans_rqst(acq_tbl,prod.seqno , prod.seqno, RETRANS_RQST_CAUSE_RCV_ERR); } acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno; } #endif ds_free(); prod.head = NULL; prod.tail = NULL; if (PNGINIT != 0) { pngout_end(); PNGINIT = 0; } uerror("Product definition header version %d pdhlen %d", pdh->version, pdh->len); uerror("PDH transfer type %u", pdh->transtype); if ((pdh->transtype & 8) > 0) uerror("Product transfer flag error %u", pdh->transtype); if ((pdh->transtype & 32) > 0) uerror("Product transfer flag error %u", pdh->transtype); uerror("header length %ld [pshlen = %d]", pdh->len + pdh->pshlen, pdh->pshlen); uerror("blocks per record %ld records per block %ld", pdh->blocks_per_record, pdh->records_per_block); uerror("product seqnumber %ld block number %ld data block " "size %ld", pdh->seqno, pdh->dbno, pdh->dbsize); uerror("product header flag %d", psh->hflag); uerror("prodspecific data length %ld", psh->psdl); uerror("bytes per record %ld", psh->bytes_per_record); uerror("Fragments = %ld category %d", psh->frags, psh->pcat); if (psh->frags < 0) uerror("check psh->frags %d", psh->frags); if (psh->origrunid != 0) uerror("original runid %d", psh->origrunid); uerror("next header offset %ld", psh->nhoff); uerror("original seq number %ld", psh->seqno); uerror("receive time %ld", psh->rectime); uerror("transmit time %ld", psh->transtime); uerror("run ID %ld", psh->runid); uerror("original run id %ld", psh->origrunid); } prod.seqno = pdh->seqno; prod.nfrag = psh->frags; ds_init(prod.nfrag); /* NWSTG CCB = dataoff, WMO = dataoff + 24 */ if (fifoRead(fifo, buf + sbn->len + pdh->len + pdh->pshlen, pdh->dbsize) != 0) { uerror("problem reading datablock"); continue; } if (sbn->datastream == 4) { if (psh->pcat != 3) { GOES = 0; NWSTG = 1; } } heapcount = 0; MD5Init(md5ctxp); if (GOES == 1) { if (readpdb(buf + IOFF + sbn->len + pdh->len + pdh->pshlen, psh, pdb, PROD_COMPRESSED, pdh->dbsize) == -1) { uerror("Error reading pdb, punt"); continue; } (void)memcpy(PROD_NAME, psh->pname, sizeof(PROD_NAME)); if (ulogIsDebug()) udebug("Read GOES %d %d %d [%d] %d", sbn->len, pdh->len, pdh->pshlen, sbn->len + pdh->len + pdh->pshlen, pdb->len); /* Data starts at first block after pdb */ ccb->len = 0; heapsize = prodalloc(psh->frags, 5152, &memheap); } if (NWSTG == 1) { memset(psh->pname, 0, sizeof(psh->pname)); if (readccb(buf + IOFF + sbn->len + pdh->len + pdh->pshlen, ccb, psh, pdh->dbsize) == -1) uerror("Error reading ccb, using default name"); if (ulogIsDebug()) udebug("look at ccb start %d %d", ccb->b1, ccb->len); if (ulogIsVerbose()) uinfo("%s", psh->pname); memcpy(PROD_NAME, psh->pname, sizeof(PROD_NAME)); heapsize = prodalloc(psh->frags, 4000 + 15, &memheap); /* * We will only compute md5 checksum on the data, 11 FOS * characters at start */ sprintf(memheap, "\001\015\015\012%03d\040\015\015\012", ((int) pdh->seqno) % 1000); heapcount += 11; if (psh->metaoff > 0) psh->metaoff = psh->metaoff + 11; } } else { /* If a continuation record...don't let psh->pcat get missed */ if ((sbn->datastream == 4) && (psh->pcat != 3)) { GOES = 0; NWSTG = 1; } ccb->len = 0; if (ulogIsDebug()) udebug("continuation record"); #ifdef RETRANS_SUPPORT if(retrans_xmit_enable == OPTION_ENABLE){ buff_hdr->buff_data_length = pdh->dbsize; buff_hdr->buff_datahdr_length = 0; buff_hdr->proc_prod_seqno= pdh->seqno; buff_hdr->proc_blkno = pdh->dbno; buff_hdr->proc_sub_code = 0; buff_hdr->proc_prod_flag = pdh->transtype; acq_tbl->proc_base_channel_type_last = buff_hdr->read_channel_type; buff_hdr->proc_prod_type = acq_tbl->proc_base_prod_type_last; buff_hdr->proc_prod_code = acq_tbl->proc_base_prod_code_last; buff_hdr->proc_prod_cat = acq_tbl->proc_base_prod_cat_last; acq_tbl->proc_prod_bytes_read += buff_hdr->buff_data_length; } #endif if ((pdh->transtype & 4) > 0) { psh->frags = 0; } if (fifoRead(fifo, buf + sbn->len + pdh->len + pdh->pshlen, pdh->dbsize) != 0) { uerror("problem reading datablock (cont)"); continue; } if (prod.head == NULL) { if (ulogIsVerbose()) uinfo("found data block before header, " "skipping sequence %d frag #%d", pdh->seqno, pdh->dbno); continue; } } /* Get the data */ dataoff = IOFF + sbn->len + pdh->len + pdh->pshlen + ccb->len; datalen = pdh->dbsize - ccb->len; if (ulogIsDebug()) udebug("look at datalen %d", datalen); pfrag = ds_alloc(); pfrag->seqno = pdh->seqno; pfrag->fragnum = pdh->dbno; pfrag->recsiz = datalen; pfrag->offset = heapcount; pfrag->next = NULL; if (GOES == 1) { if (pfrag->fragnum > 0) { if ((pfrag->fragnum != prod.tail->fragnum + 1) || (pfrag->seqno != prod.seqno)) { uerror("Missing GOES fragment in sequence, " "last %d/%d this %d/%d\0", prod.tail->fragnum, prod.seqno, pfrag->fragnum, pfrag->seqno); #ifdef RETRANS_SUPPORT if(retrans_xmit_enable == OPTION_ENABLE){ acq_tbl->proc_acqtab_prodseq_errs++; do_prod_mismatch(acq_tbl,buff_hdr); acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno; } #endif ds_free(); prod.head = NULL; prod.tail = NULL; continue; } if ((PNGINIT != 1) && (!PROD_COMPRESSED)) { uerror("failed pnginit %d %d %s", sbn->datastream, psh->pcat, PROD_NAME); continue; } if (pdh->records_per_block < 1) { uerror("records_per_block %d blocks_per_record %d " "nx %d ny %d", pdh->records_per_block, pdh->blocks_per_record, pdb->nx, pdb->ny); uerror("source %d sector %d channel %d", pdb->source, pdb->sector, pdb->channel); uerror("nrec %d recsize %d date %02d%02d%02d %02d%02d " "%02d.%02d", pdb->nrec, pdb->recsize, pdb->year, pdb->month, pdb->day, pdb->hour, pdb->minute, pdb->second, pdb->sechunds); uerror("pshname %s", psh->pname); } if (!PROD_COMPRESSED) { for (nscan = 0; (nscan * pdb->nx) < pdh->dbsize; nscan++) { if (ulogIsDebug()) udebug("png write nscan %d", nscan); if (nscan >= pdh->records_per_block) { uerror("nscan exceeding records per block %d [%d " "%d %d]", pdh->records_per_block, nscan, pdb->nx, pdh->dbsize); } else { pngwrite(buf + dataoff + (nscan * pdb->nx)); } } } else { memcpy(memheap + heapcount, buf + dataoff, datalen); MD5Update(md5ctxp, (unsigned char *) (memheap + heapcount), datalen); heapcount += datalen; } } else { if (!PROD_COMPRESSED) { png_set_memheap(memheap, md5ctxp); png_header(buf + dataoff, datalen); /* * Add 1 to number of scanlines, image ends with * f0f0f0f0... */ pngout_init(pdb->nx, pdb->ny + 1); PNGINIT = 1; } else { memcpy(memheap + heapcount, buf + dataoff, datalen); MD5Update(md5ctxp, (unsigned char*)(memheap + heapcount), datalen); heapcount += datalen; } unotice("records_per_block %d blocks_per_record %d nx %d ny %d", pdh->records_per_block, pdh->blocks_per_record, pdb->nx, pdb->ny); unotice("source %d sector %d channel %d", pdb->source, pdb->sector, pdb->channel); unotice("nrec %d recsize %d date %02d%02d%02d %02d%02d " "%02d.%02d", pdb->nrec, pdb->recsize, pdb->year, pdb->month, pdb->day, pdb->hour, pdb->minute, pdb->second, pdb->sechunds); unotice("pshname %s", psh->pname); } deflen = 0; #ifdef RETRANS_SUPPORT if(retrans_xmit_enable == OPTION_ENABLE){ if(buff_hdr->proc_blkno != 0){ /*acq_tbl->proc_prod_bytes_read += buff_hdr->buff_data_length;*/ acq_tbl->proc_prod_bytes_read += datalen; } } #endif } else { /* If the product already has a FOS trailer, don't add * another....this will match what pqing(SDI) sees */ if ((prod.nfrag != 0) && (prod.tail != NULL)) { if ((pfrag->fragnum != prod.tail->fragnum + 1) || (pfrag->seqno != prod.seqno)) { uerror("Missing fragment in sequence, last %d/%d this " "%d/%d\0", prod.tail->fragnum, prod.seqno, pfrag->fragnum, pfrag->seqno); #ifdef RETRANS_SUPPORT if(retrans_xmit_enable == OPTION_ENABLE){ acq_tbl->proc_acqtab_prodseq_errs++; if(ulogIsDebug()) udebug("do_prod_mismatch() proc_base_prod_seqno_last = %d \n", acq_tbl->proc_base_prod_seqno_last); do_prod_mismatch(acq_tbl,buff_hdr); acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno; } #endif ds_free(); prod.head = NULL; prod.tail = NULL; continue; } } if ((prod.nfrag == 0) || (prod.nfrag == (pfrag->fragnum + 1))) { char testme[4]; while (datalen > 4) { memcpy(testme, buf + (dataoff + datalen - 4), 4); if (memcmp(testme, FOS_TRAILER, 4) == 0) { datalen -= 4; if (ulogIsDebug()) udebug("removing FOS trailer from %s", PROD_NAME); } else { break; } } } if (heapcount + datalen > heapsize) { /* * this above wasn't big enough heapsize = * prodalloc(psh->frags,4000+15,&memheap); */ uerror("Error in heapsize %d product size %d [%d %d], Punt!\0", heapsize, (heapcount + datalen), heapcount, datalen); #ifdef RETRANS_SUPPORT if(retrans_xmit_enable == OPTION_ENABLE){ /* Update Statistics */ acq_tbl->proc_tot_prods_lost_errs++; /* Abort entry and request retransmission */ prod_retrans_abort_entry(acq_tbl, prod.seqno, RETRANS_RQST_CAUSE_RCV_ERR); generate_retrans_rqst(acq_tbl, prod.seqno, prod.seqno, RETRANS_RQST_CAUSE_RCV_ERR); if(acq_tbl->proc_orig_prod_seqno_last != 0){ strcpy(log_buff, "RETRANS"); } log_prod_end(log_buff, acq_tbl->proc_orig_prod_seqno_last, buff_hdr->proc_prod_seqno,buff_hdr->proc_blkno, buff_hdr->proc_prod_code, acq_tbl->proc_prod_bytes_read, acq_tbl->proc_prod_start_time); acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno; } #endif continue; } memcpy(memheap + heapcount, buf + dataoff, datalen); deflen = datalen; MD5Update(md5ctxp, (unsigned char *) (memheap + heapcount), deflen); #ifdef RETRANS_SUPPORT if(retrans_xmit_enable == OPTION_ENABLE){ if(buff_hdr->proc_blkno != 0){ /*acq_tbl->proc_prod_bytes_read += buff_hdr->buff_data_length;*/ acq_tbl->proc_prod_bytes_read += datalen; } } #endif } pfrag->recsiz = deflen; heapcount += deflen; if (prod.head == NULL) { prod.head = pfrag; prod.tail = pfrag; } else { prod.tail->next = pfrag; prod.tail = pfrag; } #ifdef RETRANS_SUPPORT if(((prod.nfrag == 0) || (prod.nfrag >= (pfrag->fragnum +1))) && (save_prod == 0)){ if(ulogIsVerbose()) uinfo("Do not save prod [seqno=%ld] as its retrans dup fragnum/total fragments =[%d of %d] save_prod=[%d] \n", prod.seqno,pfrag->fragnum,prod.nfrag,save_prod); ds_free (); prod.head = NULL; prod.tail = NULL; PNGINIT = 0; }else{ #endif if ((prod.nfrag == 0) || (prod.nfrag == (pfrag->fragnum + 1))) { if (GOES == 1) { if (PNGINIT == 1) { pngout_end(); heapcount = png_get_prodlen(); } else { if (ulogIsDebug()) udebug("GOES product already compressed %d", heapcount); } } if (ulogIsVerbose()) uinfo("we should have a complete product %ld %ld/%ld %ld /heap " "%ld", prod.seqno, pfrag->seqno, prod.nfrag, pfrag->fragnum, (long) heapcount); if ((NWSTG == 1) && (heapcount > 4)) { cnt = 4; /* number of bytes to add for TRAILER */ /* * Do a DDPLUS vs HDS check for NWSTG channel only */ if (sbn->datastream == 5) { /* nwstg channel */ switch (psh->pcat) { case 1: case 7: /* Do a quick check for non-ascii text products */ if (!prod_isascii(PROD_NAME, memheap, heapcount)) psh->pcat += 100; /* call these HDS */ break; } } if (cnt > 0) { memcpy(memheap + heapcount, FOS_TRAILER + 4 - cnt, cnt); MD5Update(md5ctxp, (unsigned char*)(memheap + heapcount), cnt); heapcount += cnt; } } #ifdef RETRANS_SUPPORT if((retrans_xmit_enable == OPTION_ENABLE) && (acq_tbl->read_distrib_enable & READ_CTL_DISCARD)){ num_prod_discards++; /* Set discard_prod to 1; Otherwise already stored prod may be requested for retransmit */ discard_prod=1; if(ulogIsVerbose()) uinfo("No of products discarded = %ld prod.seqno=%ld \n ",num_prod_discards,prod.seqno); prod_retrans_abort_entry(acq_tbl, prod.seqno, RETRANS_RQST_CAUSE_RCV_ERR); acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno -1 ; ds_free (); prod.head = NULL; prod.tail = NULL; PNGINIT = 0; }else{ /* Do not insert prod into queue if its a duplicate product */ if(save_prod != 0) #endif process_prod(prod, PROD_NAME, memheap, heapcount, md5ctxp, productMaker->ldmProdQueue, psh, sbn); #ifdef RETRANS_SUPPORT /* Update acq table with last processed seqno -Begin */ if(retrans_xmit_enable == OPTION_ENABLE){ acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno; uinfo(" prod with seqno processed = %ld\n",acq_tbl->proc_base_prod_seqno_last); } /* Update acq table with last processed seqno -End */ #endif ds_free(); prod.head = NULL; prod.tail = NULL; PNGINIT = 0; (void)pthread_mutex_lock(&productMaker->mutex); productMaker->nprods++; (void)pthread_mutex_unlock(&productMaker->mutex); #ifdef RETRANS_SUPPORT } #endif } else { if (ulogIsDebug()) udebug("processing record %ld [%ld %ld]", prod.seqno, prod.nfrag, pfrag->fragnum); if ((pdh->transtype & 4) > 0) { uerror("Hmmm....should call completed product %ld [%ld %ld]", prod.seqno, prod.nfrag, pfrag->fragnum); } } #ifdef RETRANS_SUPPORT if(retrans_xmit_enable == OPTION_ENABLE){ if(!(acq_tbl->read_distrib_enable & READ_CTL_DISCARD)) if(!discard_prod){ acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno; discard_prod = 0; } } #endif #ifdef RETRANS_SUPPORT } save_prod = 1; #endif IOFF += (sbn->len + pdh->len + pdh->pshlen + pdh->dbsize); if (ulogIsDebug()) udebug("look IOFF %ld datalen %ld (deflate %ld)", IOFF, datalen, deflen); #ifdef RETRANS_SUPPORT if(retrans_xmit_enable == OPTION_ENABLE){ total_prods_retrans_rcvd = acq_tbl->proc_tot_prods_retrans_rcvd; /* prods retrans rcvd by proc */ total_prods_retrans_rcvd_lost = acq_tbl->proc_tot_prods_retrans_rcvd_lost; /* prods retrans rcvd lost */ total_prods_retrans_rcvd_notlost = acq_tbl->proc_tot_prods_retrans_rcvd_notlost; /* prods rcvd not lost */ total_prods_retrans_rqstd = acq_tbl->proc_tot_prods_retrans_rqstd; /* prods retrans requested */ total_prods_handled = acq_tbl->proc_tot_prods_handled; /* prods retrans requested */ total_prods_lost_err = acq_tbl->proc_tot_prods_lost_errs; /* prods retrans requested */ total_frame_cnt = acq_tbl->read_tot_buff_read; total_frame_err = acq_tbl->read_frame_tot_lost_errs; proc_orig_prod_seqno_last_save = acq_tbl->proc_orig_prod_seqno_last; } #endif } if (NULL != memheap) free(memheap); productMaker->status = status; return NULL; }
static usbh_baseclassdriver_t *_ftdi_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) { int i; USBHFTDIDriver *ftdip; if (dev->devDesc.idVendor != 0x0403) { uerr("FTDI: Unrecognized VID"); return NULL; } switch (dev->devDesc.idProduct) { case 0x6001: case 0x6010: case 0x6011: case 0x6014: case 0x6015: break; default: uerr("FTDI: Unrecognized PID"); return NULL; } if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_INTERFACE)) return NULL; const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t * const)descriptor; if (ifdesc->bInterfaceNumber != 0) { uwarn("FTDI: Will allocate driver along with IF #0"); } /* alloc driver */ for (i = 0; i < HAL_USBHFTDI_MAX_INSTANCES; i++) { if (USBHFTDID[i].dev == NULL) { ftdip = &USBHFTDID[i]; goto alloc_ok; } } uwarn("FTDI: Can't alloc driver"); /* can't alloc */ return NULL; alloc_ok: /* initialize the driver's variables */ ftdip->ports = 0; switch (dev->devDesc.bcdDevice) { case 0x200: //AM uinfo("FTDI: Type A chip"); ftdip->type = USBHFTDI_TYPE_A; break; case 0x400: //BM case 0x500: //2232C case 0x600: //R case 0x1000: //230X uinfo("FTDI: Type B chip"); ftdip->type = USBHFTDI_TYPE_B; break; case 0x700: //2232H; case 0x800: //4232H; case 0x900: //232H; uinfo("FTDI: Type H chip"); ftdip->type = USBHFTDI_TYPE_H; default: uerr("FTDI: Unrecognized chip type"); return NULL; } usbhEPSetName(&dev->ctrl, "FTD[CTRL]"); /* parse the configuration descriptor */ generic_iterator_t iep, icfg; if_iterator_t iif; cfg_iter_init(&icfg, dev->fullConfigurationDescriptor, dev->basicConfigDesc.wTotalLength); for (if_iter_init(&iif, &icfg); iif.valid; if_iter_next(&iif)) { const usbh_interface_descriptor_t *const ifdesc = if_get(&iif); uinfof("FTDI: Interface #%d", ifdesc->bInterfaceNumber); USBHFTDIPortDriver *const prt = _find_port(); if (prt == NULL) { uwarn("\tCan't alloc port for this interface"); break; } prt->ifnum = ifdesc->bInterfaceNumber; prt->epin.status = USBH_EPSTATUS_UNINITIALIZED; prt->epout.status = USBH_EPSTATUS_UNINITIALIZED; for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) { const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep); if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { uinfof("BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&prt->epin, dev, epdesc); usbhEPSetName(&prt->epin, "FTD[BIN ]"); } else if (((epdesc->bEndpointAddress & 0x80) == 0) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { uinfof("BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&prt->epout, dev, epdesc); usbhEPSetName(&prt->epout, "FTD[BOUT]"); } else { uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bmAttributes); } } if ((prt->epin.status != USBH_EPSTATUS_CLOSED) || (prt->epout.status != USBH_EPSTATUS_CLOSED)) { uwarn("\tCouldn't find endpoints; can't alloc port for this interface"); continue; } /* link the new block driver to the list */ prt->next = ftdip->ports; ftdip->ports = prt; prt->ftdip = ftdip; prt->state = USBHFTDIP_STATE_ACTIVE; } return (usbh_baseclassdriver_t *)ftdip; }
/* * Send a product from file-descriptor to clnt using LDM-6 protocol. */ static void send_product_6(CLIENT *clnt, int fd, prod_info *infop) { unsigned size = infop->sz; if (size <= max_hereis) { /* * The file is small enough to be sent in a single HEREIS message. */ void* buf = (char*)malloc(size); udebug("Sending file via HEREIS"); if (NULL == buf) { serror("Couldn't allocate %u bytes for product data", size); } else { ssize_t nread = read(fd, buf, size); if(nread != size) { serror("Couldn't read %u bytes of data", size); } else { product product; product.info = *infop; product.data = buf; if (NULL == hereis_6(&product, clnt)) { uerror("%s: HEREIS_6 failure: %s", remote, clnt_errmsg(clnt)); } } free(buf); } } else { /* * The file is so large that it must be sent via COMINGSOON/BLKDATA * messages. */ comingsoon_reply_t* reply; comingsoon_args soonArg; udebug("Sending file via COMINGSOON/BLKDATA"); soonArg.infop = infop; soonArg.pktsz = size; reply = comingsoon_6(&soonArg, clnt); if (NULL == reply) { uerror("%s: COMINGSOON_6 failure: %s", remote, clnt_errmsg(clnt)); } else { if (DONT_SEND == *reply) { if (ulogIsVerbose() || ulogIsDebug()) uinfo("Downstream LDM says don't send: %s", s_prod_info(NULL, 0, infop, ulogIsDebug())); } else if (0 != *reply) { uwarn("Unexpected reply (%s) from downstream LDM: %s", s_prod_info(NULL, 0, infop, ulogIsDebug())); } else { void* buf = (char*)malloc(size); if (NULL == buf) { serror("Couldn't allocate %u bytes for product data", size); } else { ssize_t nread = read(fd, buf, size); if(nread != size) { serror("Couldn't read %u bytes of data", size); } else { datapkt packet; packet.signaturep = (signaturet*)&infop->signature; packet.pktnum = 0; packet.data.dbuf_len = size; packet.data.dbuf_val = buf; if (NULL == blkdata_6(&packet, clnt)) { uerror("%s: BLKDATA_6 failure: %s", remote, clnt_errmsg(clnt)); } } free(buf); } } } } }
static usbh_baseclassdriver_t *_msd_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) { int i; USBHMassStorageDriver *msdp; uint8_t luns; usbh_urbstatus_t stat; if (_usbh_match_descriptor(descriptor, rem, USBH_DT_INTERFACE, 0x08, 0x06, 0x50) != HAL_SUCCESS) return NULL; const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t *)descriptor; if ((ifdesc->bAlternateSetting != 0) || (ifdesc->bNumEndpoints < 2)) { return NULL; } /* alloc driver */ for (i = 0; i < HAL_USBHMSD_MAX_INSTANCES; i++) { if (USBHMSD[i].dev == NULL) { msdp = &USBHMSD[i]; goto alloc_ok; } } uwarn("Can't alloc MSD driver"); /* can't alloc */ return NULL; alloc_ok: /* initialize the driver's variables */ msdp->epin.status = USBH_EPSTATUS_UNINITIALIZED; msdp->epout.status = USBH_EPSTATUS_UNINITIALIZED; msdp->max_lun = 0; msdp->tag = 0; msdp->luns = 0; msdp->ifnum = ifdesc->bInterfaceNumber; usbhEPSetName(&dev->ctrl, "MSD[CTRL]"); /* parse the configuration descriptor */ if_iterator_t iif; generic_iterator_t iep; iif.iad = 0; iif.curr = descriptor; iif.rem = rem; for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) { const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep); if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { uinfof("BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&msdp->epin, dev, epdesc); usbhEPSetName(&msdp->epin, "MSD[BIN ]"); } else if (((epdesc->bEndpointAddress & 0x80) == 0) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { uinfof("BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&msdp->epout, dev, epdesc); usbhEPSetName(&msdp->epout, "MSD[BOUT]"); } else { uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bmAttributes); } } if ((msdp->epin.status != USBH_EPSTATUS_CLOSED) || (msdp->epout.status != USBH_EPSTATUS_CLOSED)) { goto deinit; } /* read the number of LUNs */ uinfo("Reading Max LUN:"); USBH_DEFINE_BUFFER(uint8_t buff[4]); stat = usbhControlRequest(dev, USBH_REQTYPE_CLASSIN(USBH_REQTYPE_RECIP_INTERFACE), MSD_GET_MAX_LUN, 0, msdp->ifnum, 1, buff); if (stat == USBH_URBSTATUS_OK) { msdp->max_lun = buff[0] + 1; uinfof("\tmax_lun = %d", msdp->max_lun); if (msdp->max_lun > HAL_USBHMSD_MAX_LUNS) { msdp->max_lun = HAL_USBHMSD_MAX_LUNS; uwarnf("\tUsing max_lun = %d", msdp->max_lun); } } else if (stat == USBH_URBSTATUS_STALL) { uwarn("\tStall, max_lun = 1"); msdp->max_lun = 1; } else { uerr("\tError"); goto deinit; } /* open the bulk IN/OUT endpoints */ usbhEPOpen(&msdp->epin); usbhEPOpen(&msdp->epout); /* Alloc one block device per logical unit found */ luns = msdp->max_lun; for (i = 0; (luns > 0) && (i < HAL_USBHMSD_MAX_LUNS); i++) { if (MSBLKD[i].msdp == NULL) { /* link the new block driver to the list */ MSBLKD[i].next = msdp->luns; msdp->luns = &MSBLKD[i]; MSBLKD[i].msdp = msdp; MSBLKD[i].state = BLK_ACTIVE; luns--; } } return (usbh_baseclassdriver_t *)msdp; deinit: /* Here, the enpoints are closed, and the driver is unlinked */ return NULL; }
static msd_bot_result_t _msd_bot_transaction(msd_transaction_t *tran, USBHMassStorageLUNDriver *lunp, void *data) { uint32_t data_actual_len, actual_len; usbh_urbstatus_t status; USBH_DEFINE_BUFFER(msd_csw_t csw); tran->cbw->bCBWLUN = (uint8_t)(lunp - &lunp->msdp->luns[0]); tran->cbw->dCBWSignature = MSD_CBW_SIGNATURE; tran->cbw->dCBWTag = ++lunp->msdp->tag; tran->data_processed = 0; /* control phase */ status = usbhBulkTransfer(&lunp->msdp->epout, tran->cbw, sizeof(*tran->cbw), &actual_len, OSAL_MS2I(1000)); if (status == USBH_URBSTATUS_CANCELLED) { uerr("\tMSD: Control phase: USBH_URBSTATUS_CANCELLED"); return MSD_BOTRESULT_DISCONNECTED; } if ((status != USBH_URBSTATUS_OK) || (actual_len != sizeof(*tran->cbw))) { uerrf("\tMSD: Control phase: status = %d (!= OK), actual_len = %d (expected to send %d)", status, actual_len, sizeof(*tran->cbw)); _msd_bot_reset(lunp->msdp); return MSD_BOTRESULT_ERROR; } /* data phase */ data_actual_len = 0; if (tran->cbw->dCBWDataTransferLength) { usbh_ep_t *const ep = tran->cbw->bmCBWFlags & MSD_CBWFLAGS_D2H ? &lunp->msdp->epin : &lunp->msdp->epout; status = usbhBulkTransfer( ep, data, tran->cbw->dCBWDataTransferLength, &data_actual_len, OSAL_MS2I(20000)); if (status == USBH_URBSTATUS_CANCELLED) { uerr("\tMSD: Data phase: USBH_URBSTATUS_CANCELLED"); return MSD_BOTRESULT_DISCONNECTED; } if (status == USBH_URBSTATUS_STALL) { uerrf("\tMSD: Data phase: USBH_URBSTATUS_STALL, clear halt"); status = (usbhEPReset(ep) == HAL_SUCCESS) ? USBH_URBSTATUS_OK : USBH_URBSTATUS_ERROR; } if (status != USBH_URBSTATUS_OK) { uerrf("\tMSD: Data phase: status = %d (!= OK), resetting", status); _msd_bot_reset(lunp->msdp); return MSD_BOTRESULT_ERROR; } } /* status phase */ status = usbhBulkTransfer(&lunp->msdp->epin, &csw, sizeof(csw), &actual_len, OSAL_MS2I(1000)); if (status == USBH_URBSTATUS_STALL) { uwarn("\tMSD: Status phase: USBH_URBSTATUS_STALL, clear halt and retry"); status = (usbhEPReset(&lunp->msdp->epin) == HAL_SUCCESS) ? USBH_URBSTATUS_OK : USBH_URBSTATUS_ERROR; if (status == USBH_URBSTATUS_OK) { status = usbhBulkTransfer(&lunp->msdp->epin, &csw, sizeof(csw), &actual_len, OSAL_MS2I(1000)); } } if (status == USBH_URBSTATUS_CANCELLED) { uerr("\tMSD: Status phase: USBH_URBSTATUS_CANCELLED"); return MSD_BOTRESULT_DISCONNECTED; } if (status != USBH_URBSTATUS_OK) { uerrf("\tMSD: Status phase: status = %d (!= OK), resetting", status); _msd_bot_reset(lunp->msdp); return MSD_BOTRESULT_ERROR; } /* validate CSW */ if ((actual_len != sizeof(csw)) || (csw.dCSWSignature != MSD_CSW_SIGNATURE) || (csw.dCSWTag != lunp->msdp->tag) || (csw.bCSWStatus >= CSW_STATUS_PHASE_ERROR)) { /* CSW is not valid */ uerrf("\tMSD: Status phase: Invalid CSW: len=%d, dCSWSignature=%x, dCSWTag=%x (expected %x), bCSWStatus=%d, resetting", actual_len, csw.dCSWSignature, csw.dCSWTag, lunp->msdp->tag, csw.bCSWStatus); _msd_bot_reset(lunp->msdp); return MSD_BOTRESULT_ERROR; } /* check if CSW is meaningful */ if ((csw.bCSWStatus != CSW_STATUS_PHASE_ERROR) && (csw.dCSWDataResidue > tran->cbw->dCBWDataTransferLength)) { /* CSW is not meaningful */ uerrf("\tMSD: Status phase: CSW not meaningful: bCSWStatus=%d, dCSWDataResidue=%u, dCBWDataTransferLength=%u, resetting", csw.bCSWStatus, csw.dCSWDataResidue, tran->cbw->dCBWDataTransferLength); _msd_bot_reset(lunp->msdp); return MSD_BOTRESULT_ERROR; } if (csw.bCSWStatus == CSW_STATUS_PHASE_ERROR) { uerr("\tMSD: Status phase: Phase error, resetting"); _msd_bot_reset(lunp->msdp); return MSD_BOTRESULT_ERROR; } tran->data_processed = tran->cbw->dCBWDataTransferLength - csw.dCSWDataResidue; if (data_actual_len < tran->data_processed) { tran->data_processed = data_actual_len; } tran->csw_status = csw.bCSWStatus; return MSD_BOTRESULT_OK; }
/** * Reads a NOAAPORT data stream, creates LDM data-products from the stream, and * inserts the data-products into an LDM product-queue. The NOAAPORT data * stream can take the form of multicast UDP packets from (for example) a * Novra S300 DVB-S2 receiver or the standard input stream. * * Usage: * noaaportIngester [-l <em>log</em>] [-n|-v|-x] [-q <em>queue</em>] [-u <em>n</em>] [-m <em>mcastAddr</em>] [-I <em>iface</em>] [-b <em>npages</em>]\n * * Where: * <dl> * <dt>-b <em>npages</em></dt> * <dd>Allocate \e npages pages of memory for the internal buffer.</dd> * * <dt>-I <em>iface</em></dt> * <dd>Listen for multicast packets on interface \e iface.</dd> * * <dt>-l <em>log</em></dt> * <dd>Log to file \e log. The default is to use the system logging daemon * if the current process is a daemon; otherwise, the standard error * stream is used.</dd> * * <dt>-m <em>mcastAddr</em></dt> * <dd>Use the multicast address \e mcastAddr. The default is to * read from the standard input stream.</dd> * * <dt>-n</dt> * <dd>Log messages of level NOTE and higher priority. Each data-product * will generate a log message.</dd> * * <dt>-q <em>queue</em></dt> * <dd>Use \e queue as the pathname of the LDM product-queue. The default * is to use the default LDM pathname of the product-queue.</dd> * * <dt>-u <em>n</em></dt> * <dd>If logging is to the system logging daemon, then use facility * <b>local</b><em>n</em>. The default is to use the LDM facility.</dd> * * <dt>-v</dt> * <dd>Log messages of level INFO and higher priority.</dd> * * <dt>-x</dt> * <dd>Log messages of level DEBUG and higher priority.</dd> * </dl> * * If neither -n, -v, nor -x is specified, then logging will be restricted to * levels ERROR and WARN only. * * @retval 0 if successful. * @retval 1 if an error occurred. At least one error-message will be logged. */ int main( const int argc, /**< [in] Number of arguments */ char* const argv[]) /**< [in] Arguments */ { int status = 0; /* default success */ extern int optind; extern int opterr; int ch; const char* const progName = ubasename(argv[0]); const char* interface = NULL; int logmask = LOG_UPTO(LOG_WARNING); const unsigned logOptions = LOG_CONS | LOG_PID; const char* mcastSpec = NULL; const char* prodQueuePath = NULL; size_t npages = DEFAULT_NPAGES; Fifo* fifo; int ttyFd = open("/dev/tty", O_RDONLY); int processPriority = 0; int idx; const char* logPath = (-1 == ttyFd) ? NULL /* log to system logging daemon */ : "-"; /* log to standard error stream */ (void)close(ttyFd); (void)setulogmask(logmask); status = initLogging(progName, logOptions, logFacility, logPath); opterr = 0; /* no error messages from getopt(3) */ while (0 == status && (ch = getopt(argc, argv, "b:I:l:m:np:q:r:s:t:u:vx")) != -1) { switch (ch) { extern char* optarg; extern int optopt; case 'b': { unsigned long n; if (sscanf(optarg, "%lu", &n) != 1) { LOG_SERROR1("Couldn't decode FIFO size in pages: \"%s\"", optarg); status = 1; } else { npages = n; } break; } case 'I': interface = optarg; break; case 'l': logPath = optarg; status = initLogging(progName, logOptions, logFacility, logPath); break; case 'm': mcastSpec = optarg; break; case 'n': logmask |= LOG_MASK(LOG_NOTICE); (void)setulogmask(logmask); break; case 'p': { char* cp; errno = 0; processPriority = (int)strtol(optarg, &cp, 0); if (0 != errno) { LOG_SERROR1("Couldn't decode priority \"%s\"", optarg); log_log(LOG_ERR); } else { if (processPriority < -20) processPriority = -20; else if (processPriority > 20) processPriority = 20; } break; } case 'q': prodQueuePath = optarg; break; case 'r': #ifdef RETRANS_SUPPORT retrans_xmit_enable = atoi(optarg); if(retrans_xmit_enable == 1) retrans_xmit_enable = OPTION_ENABLE; else retrans_xmit_enable = OPTION_DISABLE; #endif break; case 's': { #ifdef RETRANS_SUPPORT strcpy(sbn_channel_name, optarg); if(!strcmp(optarg,NAME_SBN_TYP_GOES)) { sbn_type = SBN_TYP_GOES; break; } if(!strcmp(optarg,NAME_SBN_TYP_NOAAPORT_OPT)) { sbn_type = SBN_TYP_NOAAPORT_OPT; break; } if(!strcmp(optarg,"NWSTG")) { sbn_type = SBN_TYP_NMC; break; } if(!strcmp(optarg,NAME_SBN_TYP_NMC)) { sbn_type = SBN_TYP_NMC; break; } if(!strcmp(optarg,NAME_SBN_TYP_NMC2)) { sbn_type = SBN_TYP_NMC2; break; } if(!strcmp(optarg,NAME_SBN_TYP_NMC3)) { sbn_type = SBN_TYP_NMC3; break; } if(!strcmp(optarg,NAME_SBN_TYP_NWWS)) { sbn_type = SBN_TYP_NWWS; break; } if(!strcmp(optarg,NAME_SBN_TYP_ADD)) { sbn_type = SBN_TYP_ADD; break; } if(!strcmp(optarg,NAME_SBN_TYP_ENC)) { sbn_type = SBN_TYP_ENC; break; } if(!strcmp(optarg,NAME_SBN_TYP_EXP)) { sbn_type = SBN_TYP_EXP; break; } if(!strcmp(optarg,NAME_SBN_TYP_GRW)) { sbn_type = SBN_TYP_GRW; break; } if(!strcmp(optarg,NAME_SBN_TYP_GRE)) { sbn_type = SBN_TYP_GRE; break; } printf("Operator input: UNKNOWN type must be\n"); printf(" %s, %s, %s, %s, %s, %s, %s, %s, %s, %s or %s \n", NAME_SBN_TYP_NMC, NAME_SBN_TYP_GOES, NAME_SBN_TYP_NOAAPORT_OPT, NAME_SBN_TYP_NMC2, NAME_SBN_TYP_NMC3, NAME_SBN_TYP_NWWS, NAME_SBN_TYP_ADD, NAME_SBN_TYP_ENC, NAME_SBN_TYP_EXP, NAME_SBN_TYP_GRW, NAME_SBN_TYP_GRE); #endif break; } case 't': #ifdef RETRANS_SUPPORT strcpy(transfer_type, optarg); if(!strcmp(transfer_type,"MHS") || !strcmp(transfer_type,"mhs")){ /** Using MHS for communication with NCF **/ }else{ uerror("No other mechanism other than MHS is currently supported\n"); status = 1; } #endif break; case 'u': { int i = atoi(optarg); if (0 > i || 7 < i) { LOG_START1("Invalid logging facility number: %d", i); status = 1; } else { static int logFacilities[] = {LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7}; logFacility = logFacilities[i]; status = initLogging(progName, logOptions, logFacility, logPath); } break; } case 'v': logmask |= LOG_MASK(LOG_INFO); (void)setulogmask(logmask); break; case 'x': logmask |= LOG_MASK(LOG_DEBUG); (void)setulogmask(logmask); break; default: optopt = ch; /*FALLTHROUGH*/ /* no break */ case '?': { uerror("Unknown option: \"%c\"", optopt); status = 1; break; } } /* option character switch */ } /* getopt() loop */ if (0 == status) { if (optind < argc) { uerror("Extraneous command-line argument: \"%s\"", argv[optind]); status = 1; } } if (0 != status) { uerror("Error decoding command-line"); usage(progName); } else { unotice("Starting Up %s", PACKAGE_VERSION); unotice("%s", COPYRIGHT_NOTICE); if ((status = fifoNew(npages, &fifo)) != 0) { LOG_ADD0("Couldn't create FIFO"); log_log(LOG_ERR); } else { LdmProductQueue* prodQueue; if ((status = lpqGet(prodQueuePath, &prodQueue)) != 0) { LOG_ADD0("Couldn't open LDM product-queue"); log_log(LOG_ERR); } else { if (NULL == mcastSpec) { if (0 == (status = spawnProductMaker(NULL, fifo, prodQueue, &productMaker, &productMakerThread))) { status = spawnFileReader(NULL, NULL, fifo, &reader, &readerThread); } } /* reading file */ else { pthread_attr_t attr; if (0 != (status = pthread_attr_init(&attr))) { LOG_ERRNUM0(status, "Couldn't initialize thread attribute"); } else { #ifndef _POSIX_THREAD_PRIORITY_SCHEDULING uwarn("Can't adjust thread priorities due to lack of " "necessary support from environment"); #else /* * In order to not miss any data, the reader thread * should preempt the product-maker thread as soon as * data is available and run as long as data is * available. */ const int SCHED_POLICY = SCHED_FIFO; struct sched_param param; param.sched_priority = sched_get_priority_max(SCHED_POLICY) - 1; (void)pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); (void)pthread_attr_setschedpolicy(&attr, SCHED_POLICY); (void)pthread_attr_setschedparam(&attr, ¶m); (void)pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); #endif #ifdef RETRANS_SUPPORT if (retrans_xmit_enable == OPTION_ENABLE){ /* Copy mcastAddress needed to obtain the cpio entries */ strcpy(mcastAddr, mcastSpec); } #endif if (0 == (status = spawnProductMaker(&attr, fifo, prodQueue, &productMaker, &productMakerThread))) { #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING param.sched_priority++; (void)pthread_attr_setschedparam(&attr, ¶m); #endif status = spawnMulticastReader(&attr, mcastSpec, interface, fifo, &reader, &readerThread); } /* product-maker spawned */ } /* "attr" initialized */ } /* reading multicast packets */ if (0 != status) { log_log(LOG_ERR); status = 1; } else { pthread_t statThread; (void)gettimeofday(&startTime, NULL); reportTime = startTime; (void)pthread_create(&statThread, NULL, reportStatsWhenSignaled, NULL); set_sigactions(); (void)pthread_join(readerThread, NULL); status = readerStatus(reader); (void)pthread_cancel(statThread); (void)pthread_join(statThread, NULL); (void)fifoCloseWhenEmpty(fifo); (void)pthread_join(productMakerThread, NULL); if (0 != status) status = pmStatus(productMaker); reportStats(); readerFree(reader); #ifdef RETRANS_SUPPORT /** Release buffer allocated for retransmission **/ if(retrans_xmit_enable == OPTION_ENABLE){ freeRetransMem(); } #endif } /* "reader" spawned */ (void)lpqClose(prodQueue); } /* "prodQueue" open */ } /* "fifo" created */ } /* command line decoded */ return status; }