int run_client(struct list_loop *ls, struct task_loop *tl, int mask) { struct mul_client *ci; int update, idle, result; #if 0 struct task_loop *tx; #endif struct link_loop *lk; struct mul_msg *mm; ci = user_loop(ls, tl); if(ci == NULL){ stop_loop(ls, tl); return 0; } ci->c_task = tl; idle = LO_STOP_MASK | LO_WAIT_MASK; #ifdef DEBUG fprintf(stderr, "client[%p]: mask 0x%02x\n", tl, mask); #endif update = idle; if(mask & LO_STOP_MASK){ /* WARNING: may have to remove fd to prevent almost harmless but ugly double close */ shutdown_client(ci); return 0; } /* handle read case */ update |= LO_READ_MASK; if(mask & LO_READ_MASK){ result = read_katcp(ci->c_dispatch); #ifdef DEBUG fprintf(stderr, "client: read code is %d\n", result); #endif if(result < 0){ stop_loop(ls, tl); return 0; } if(result > 0){ update &= ~(LO_READ_MASK); /* on EOF stop reading */ } } /* handle work function */ result = lookup_katcp(ci->c_dispatch); if(result < 0){ stop_loop(ls, tl); return 0; } if(result > 0){ /* WARNING: statement triggers dispatch if no request pending (new) or if something has arrived (with pending request) */ if((ci->c_waiting == 0) || (mask & LO_WAIT_MASK)){ #ifdef DEBUG fprintf(stderr, "client[%p]: calling dispatch (queue=%d)\n", tl, ci->c_queue); #endif result = call_katcp(ci->c_dispatch); if(result == KATCP_RESULT_RESUME){ ci->c_waiting = (ci->c_queue > 0) ? 1 : 0; } else { ci->c_waiting = 0; if(ci->c_queue > 0){ /* WARNING: this should actually be an abort, as the dispatch routines have broken the queue */ fprintf(stderr, "client[%p]: warning: finished with %d outstanding requests\n", tl, ci->c_queue); log_message_katcp(ci->c_dispatch, KATCP_LEVEL_ERROR, NULL, "client function has %d outstand requests", ci->c_queue); } ci->c_queue = 0; } } } if(mask & LO_WAIT_MASK){ if(!(ci->c_waiting)){ /* no dispatch function busy, so we handle the informs and ditch everything else */ #ifdef DEBUG fprintf(stderr, "client[%p]: idle, handling queue\n", tl); #endif while((lk = receive_link_loop(ls, tl)) != NULL){ #ifdef DEBUG fprintf(stderr, "client[%p]: received event type %d\n", tl, lk->k_type); #endif if((lk->k_type == ci->c_overall->o_type_msg) && (lk->k_data != NULL)){ mm = lk->k_data; if(arg_inform_msg(mm)){ /* inform messages get sent out */ dispatch_from_msg(ci->c_dispatch, mm); } } discard_link_loop(ls, lk); } } } /* handle write case */ if(mask & LO_WRITE_MASK){ if(write_katcp(ci->c_dispatch) < 0){ stop_loop(ls, tl); return 0; } } if(flushing_katcp(ci->c_dispatch)){ /* WARNING: could disable reads and running if flush buffer too large */ update |= LO_WRITE_MASK; } if(update == idle){ /* if we are only interested in stopping then stop */ stop_loop(ls, tl); } set_mask_loop(ls, tl, update, 0); if(exited_katcp(ci->c_dispatch) != KATCP_EXIT_NOTYET){ /* TODO: make it stop */ } return 0; }
int main(int argc, char **argv) { struct udp_state *ud; struct katcp_dispatch *d; unsigned int result; struct timeval now; fd_set fsr; char *ip_addr = NULL; uint32_t address, length; int i, j, c, pos; int wait, nooftries; int port = 0; int rw_flag = 0; i = j = 1; pos = 0; wait = 0; nooftries = 10; while (i < argc) { if (argv[i][0] == '-') { c = argv[i][j]; switch (c) { case '\0': j = 1; i++; break; case '-' : j++; break; case 'h' : fprintf(stderr, "usage: %s -R [-i ipaddress] [-p port] address length\n", argv[0]); return 0; break; case 'i' : j++; if(argv[i][j] == '\0'){ j = 0; i++; } if(i >= argc){ fprintf(stderr, "%s: option -%c requires a parameter\n", argv[0], c); } ip_addr = argv[i] + j; i++; j = 1; break; case 'p' : j++; if(argv[i][j] == '\0'){ j = 0; i++; } if(i >= argc){ fprintf(stderr, "%s: option -%c requires a parameter\n", argv[0], c); } port = atoi(argv[i] + j); #if DEBUG fprintf(stderr, "port number is %d\n", port); #endif i++; j = 1; break; case 'R' : rw_flag = 1; i++; break; default: fprintf(stderr, "%s: unknown option -%c\n", argv[0], argv[i][j]); return 2; } } else { pos = i; i = argc; } } d = setup_katcp(STDOUT_FILENO); if(d == NULL){ fprintf(stderr, "setup katcp failed\n"); return EX_OSERR; } ud = create_udp(d); if(ud == NULL){ fprintf(stderr, "create udp failed\n"); log_message_katcp(d, KATCP_LEVEL_ERROR, DMON_MODULE_NAME, "unable to allocate local udp state"); write_katcp(d); return EX_OSERR; } #if 0 if(connect_udp(d, ud, port) < 0){ fprintf(stderr, "connect udp failed\n"); log_message_katcp(d, KATCP_LEVEL_ERROR, DMON_MODULE_NAME, "unable to bind udp"); return EX_OSERR; } #endif ud->u_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(ud->u_fd < 0){ fprintf(stderr, "unable to create udp socket:\n "); log_message_katcp(d, KATCP_LEVEL_ERROR, DMON_MODULE_NAME, "unable to create udp socket: %s", strerror(errno)); return -1; } ud->u_rw = rw_flag; for(;;){ FD_ZERO(&fsr); FD_SET(ud->u_fd, &fsr); address = strtol(argv[pos], NULL, 16); length = strtol(argv[pos + 1], NULL, 16); #if DEBUG printf("pos:%d, address[%x] and length[%x]\n", pos, address, length); #endif send_udp(d, ud, ip_addr, port, address, length); now.tv_sec = 10; now.tv_usec = 0; result = select(ud->u_fd + 1, &fsr, NULL, NULL, &now); if(result == 0){ /* Resend again after timeout */ printf("Resending udp again\n"); send_udp(d, ud, ip_addr, port, address, length); } for(wait = 0; wait < nooftries; wait++){ if(FD_ISSET(ud->u_fd, &fsr)){ result = rcv_udp(d, ud); if(!result){ return EX_OK; } } } return EX_OSERR; } destroy_udp(d, ud); shutdown_katcp(d); return EX_OK; }