int Service::start(int port) { if (!soap_valid_socket(bind(NULL, port, 100))) { soap_stream_fault(std::cerr); exit(1); } std::cerr << "Server Running" << std::endl; /* optional: set accept timeout to pulse acks every 500 ms, see below */ soap->accept_timeout = -500000; for (;;) { if (soap_valid_socket(accept())) { /* with iterative servers asynchronous messaging deadlock scenarios exist! */ /* chain the WSRM service operations after the main service operations */ if (soap_begin_serve(soap) == SOAP_OK) if (dispatch() == SOAP_NO_METHOD) soap_serve_request(soap); if (soap->error) soap_send_fault(soap); if (soap->error && soap->error != SOAP_STOP) soap_stream_fault(std::cerr); destroy(); callback.destroy(); soap_wsrm_dump(soap, stdout); } else { /* error or timeout? */ if (soap->errnum) { soap_stream_fault(std::cerr); exit(1); } /* timeout occurs after 1 sec */ /* send acks to peers (optional), 10 ms per message timeout */ soap_wsrm_pulse(soap, -10000); /* 10 ms */ } } return SOAP_OK; }
int Client::poll(int timeout) { #ifdef CB_THREAD // We leave the acceptance of messages to the callback server thread if (timeout < 0) timeout = 1; sleep(timeout); // but we want to wait some until these messages arrive #else callback.soap->accept_timeout = timeout; printf("\n**** Callback Polling\n"); while (soap_valid_socket(callback.accept())) { /* chain the WSRM operations after callback operations */ if (soap_begin_serve(callback.soap) == SOAP_OK) if (callback.dispatch() == SOAP_NO_METHOD) soap_serve_request(callback.soap); if (callback.soap->error) soap_send_fault(callback.soap); soap->error = callback.soap->error; callback.destroy(); if (soap->error && soap->error != SOAP_STOP) { soap_stream_fault(std::cerr); return soap->error; } soap_wsrm_dump(callback.soap, stdout); } #endif return SOAP_OK; }
int main(int argc, char* argv[]) { std::string indevice = "/dev/video0"; std::string inpath = "unicast"; std::string outdevice = "/dev/video10"; std::string outpath = "rtsp://127.0.0.1:8554/unicast"; std::string username; std::string password; int port = 8080; int c = 0; while ((c = getopt (argc, argv, "h" "u:p:" "P:" "i:I:o:O:")) != -1) { switch (c) { case 'P': port = atoi(optarg); break; case 'u': username = optarg; break; case 'p': password = optarg; break; case 'i': indevice = optarg; break; case 'I': inpath = optarg; break; case 'o': outdevice = optarg; break; case 'O': outpath = optarg; break; case 'h': std::cout << argv[0] << " [-u username] [-p password] [-i v4l2 input device] [-I rtsp server] [-o v4l2 output device] [-O rtsp client]" << std::endl; exit(0); break; } } std::cout << "Listening to " << port << std::endl; ServiceContext deviceCtx; deviceCtx.m_devices.insert(std::pair<std::string,std::string>(indevice, inpath)); deviceCtx.m_port = port; deviceCtx.m_user = username; deviceCtx.m_password = password; deviceCtx.m_outdevice = outdevice; deviceCtx.Manufacturer = "Manufacturer"; deviceCtx.Model = "Model"; deviceCtx.FirmwareVersion = "FirmwareVersion"; deviceCtx.SerialNumber = "SerialNumber"; deviceCtx.HardwareId = "HardwareId"; deviceCtx.m_scope.push_back("onvif://www.onvif.org/name/Name"); deviceCtx.m_scope.push_back("onvif://www.onvif.org/location/Here"); deviceCtx.m_scope.push_back("onvif://www.onvif.org/Profile/Streaming"); deviceCtx.m_scope.push_back("onvif://www.onvif.org/Profile/G"); struct soap *soap = soap_new(); soap->user = (void*)&deviceCtx; soap->fget = http_get; { FOREACH_SERVICE(DECLARE_SERVICE,soap) if (!soap_valid_socket(soap_bind(soap, NULL, deviceCtx.m_port, 100))) { soap_stream_fault(soap, std::cerr); } else { while (soap_accept(soap) != SOAP_OK) { if (soap_begin_serve(soap)) { soap_stream_fault(soap, std::cerr); } FOREACH_SERVICE(DISPATCH_SERVICE,soap) else { std::cout << "Unknown service" << std::endl; } } } } soap_destroy(soap); soap_end(soap); soap_free(soap); return 0; }
int Client::run() { // Create a reliable messaging sequence handle for client-initiated session soap_wsrm_sequence_handle seq; xsd__duration expires = 30000; /* 30000 ms = 30 seconds to expire */ const char *id = soap_wsa_rand_uuid(soap); double n; int retry; printf("\n**** Creating the Sequence\n"); // Create session for in-order messaging, init sequence handle if (soap_wsrm_create_offer(soap, serverURI, clientURI, id, expires, NoDiscard, soap_wsa_rand_uuid(soap), &seq)) { soap_stream_fault(std::cerr); soap_wsrm_seq_free(soap, seq); return soap->error; } // poll 100 times for .1 second until created for (retry = 100; retry && !soap_wsrm_seq_created(soap, seq); retry--) { if (poll(-100000)) return soap->error; } if (!retry) { fprintf(stderr, "CANNOT CREATE SEQUENCE - SERVER NOT RESPONDING\n"); exit(1); } // Reliable messaging request message if (soap_wsrm_request_acks(soap, seq, soap_wsa_rand_uuid(soap), "http://Microsoft.Samples.DualHttp/ICalculatorDuplex/AddTo")) { soap_stream_fault(std::cerr); return soap->error; } n = 3.14; _mssadh__AddTo addTo; addTo.n = &n; if (AddTo(&addTo) == SOAP_OK) std::cout << std::endl << "**** AddTo(" << *addTo.n << ")" << std::endl; else soap_stream_fault(std::cerr); destroy(); #ifndef CB_THREAD // callback polling: 500 ms polling cycle if (poll(-500000)) return soap->error; #endif // Reliable messaging request message if (soap_wsrm_request_acks(soap, seq, soap_wsa_rand_uuid(soap), "http://Microsoft.Samples.DualHttp/ICalculatorDuplex/SubtractFrom")) { soap_stream_fault(std::cerr); return soap->error; } n = 1.41; _mssadh__SubtractFrom subtractFrom; subtractFrom.n = &n; if (SubtractFrom(&subtractFrom) == SOAP_OK) std::cout << std::endl << "**** SubtractFrom(" << *subtractFrom.n << ")" << std::endl; else soap_stream_fault(std::cerr); destroy(); #ifndef CB_THREAD // callback polling: 500 ms polling cycle if (poll(-500000)) return soap->error; #endif // Reliable messaging request message if (soap_wsrm_request_acks(soap, seq, soap_wsa_rand_uuid(soap), "http://Microsoft.Samples.DualHttp/ICalculatorDuplex/Clear")) { soap_stream_fault(std::cerr); return soap->error; } _mssadh__Clear clear; if (Clear(&clear) == SOAP_OK) std::cout << std::endl << "**** Clear()" << std::endl; else soap_stream_fault(std::cerr); destroy(); #ifndef CB_THREAD // callback polling: 500 ms polling cycle if (poll(-500000)) return soap->error; #endif printf("\n**** Closing the Sequence\n"); if (soap_wsrm_close(soap, seq, soap_wsa_rand_uuid(soap))) { soap_stream_fault(std::cerr); soap_wsrm_seq_free(soap, seq); return soap->error; } for (retry = 10; retry; retry--) { // Receive more messages when last not yet received if (soap_wsrm_lastnum(seq) == 0) { #ifdef CB_THREAD // we want to pulse here to send acks for incoming messages to keep flow going soap_wsrm_pulse(soap, -500000); /* 500 ms */ #endif printf("\n**** Receiving Messages Until Last\n"); // callback polling or delay: 500 ms polling cycle if (poll(-500000)) return soap->error; } // Resend messages marked as non-acked (as an option) if (soap_wsrm_nack(seq)) { printf("\n**** Resending "SOAP_ULONG_FORMAT" Non-Acked Messages\n", soap_wsrm_nack(seq)); soap_wsrm_resend(soap, seq, 0, 0); /* 0 0 means full range of msg nums */ } } if (soap_wsrm_nack(seq) || soap_wsrm_lastnum(seq) == 0) { printf("\n**** Incomplete Sequence\n"); soap_wsrm_dump(soap, stdout); } printf("\n**** Terminating the Sequence\n"); // Termination fails if the server did not get all messages if (soap_wsrm_terminate(soap, seq, soap_wsa_rand_uuid(soap))) { soap_stream_fault(std::cerr); soap_wsrm_seq_free(soap, seq); return soap->error; } #ifdef CB_THREAD soap_wsrm_dump(soap, stdout); #endif // callback polling: 1 s polling cycle if (poll(1)) return soap->error; // Delete the reliable messaging session sequence (assuming no more inbound messages) soap_wsrm_seq_free(soap, seq); return 0; }