std::string jevois::getPythonExceptionString(boost::python::error_already_set &) { // Get some info from the python exception: PyObject *t, *v, *tb; try { PyErr_Fetch(&t, &v, &tb); PyErr_NormalizeException(&t, &v, &tb); } catch (...) { return "Internal error trying to fetch exception data from Python"; } try { boost::python::object objtype = ::ptr_to_obj(t); boost::python::object objvalue = ::ptr_to_obj(v); boost::python::object objtraceback = ::ptr_to_obj(tb); std::string const type = extract_exception_type(objtype); std::string const message = (type == "SyntaxError") ? make_syntax_error_message(objvalue) : extract_message(objvalue); traceback const traceback = extract_traceback(objtraceback); PyErr_Restore(t, v, tb); clear_exception(); return generate_message(type, message, traceback); } catch (...) { PyErr_Restore(t, v, tb); clear_exception(); return "Internal error trying to fetch exception data from Python"; } }
/* ------------------------------------------------------------------------- make_log_entry has 1 main flaws: The message in its entirity, must fit into the tempbuffer. So it must be shorter than MAXLOGSIZE ------------------------------------------------------------------------- */ void make_log_entry(enum loglevels loglevel, enum logtypes logtype, const char *file, int line, char *message, ...) { /* fn is not reentrant but is used in signal handler * with LOGGER it's a little late source name and line number * are already changed. */ static int inlog = 0; int fd, len; char *user_message, *log_message; va_list args; if (inlog) return; inlog = 1; if (!log_config.inited) { log_init(); } if (type_configs[logtype].syslog) { if (type_configs[logtype].level >= loglevel) { /* Initialise the Messages and send it to syslog */ va_start(args, message); len = vasprintf(&user_message, message, args); va_end(args); if (len == -1) { return; } make_syslog_entry(loglevel, logtype, user_message); free(user_message); } inlog = 0; return; } /* logging to a file */ log_src_filename = file; log_src_linenumber = line; /* Check if requested logtype is setup */ if (type_configs[logtype].set) { /* Yes */ fd = type_configs[logtype].fd; } else { /* No: use default */ fd = type_configs[logtype_default].fd; } if (fd < 0) { /* no where to send the output, give up */ goto exit; } /* Initialise the Messages */ va_start(args, message); len = vasprintf(&user_message, message, args); if (len == -1) { goto exit; } va_end(args); len = generate_message(&log_message, user_message, type_configs[logtype].set ? type_configs[logtype].display_options : type_configs[logtype_default].display_options, loglevel, logtype); if (len == -1) { goto exit; } write(fd, log_message, len); free(log_message); free(user_message); exit: inlog = 0; }
int main(int argc, char* argv[]) { signal( SIGTRAP, SIG_IGN ); params p = get_params( argc, argv ); unistd::addrinfo hint = addrinfo{ 0, AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 0, nullptr, nullptr, nullptr }; std::vector<unistd::addrinfo> addrs = unistd::getaddrinfo( p.hostname, p.port, hint ); const unistd::addrinfo& addr = addrs.at( 0 ); unistd::fd sock = unistd::socket( addr ); subscribe_events( sock ); if ( 0 != p.sndbuf ) unistd::setsockopt( sock, SOL_SOCKET, SO_SNDBUF, p.sndbuf ); if ( 0 != p.mtu ) { unistd::setsockopt( sock, IPPROTO_IPV6, IPV6_MTU_DISCOVER, IP_PMTUDISC_DONT ); unistd::setsockopt( sock, IPPROTO_IPV6, IPV6_MTU, p.mtu ); } if ( p.nodelay ) unistd::setsockopt( sock, SOL_SCTP, SCTP_NODELAY, 1 ); if ( 0 != p.max_burst ) unistd::setsockopt( sock, SOL_SCTP, SCTP_MAX_BURST, p.max_burst ); if ( 0 != p.maxseg ) unistd::setsockopt( sock, SOL_SCTP, SCTP_MAXSEG, p.maxseg ); int sndbuf = 0; socklen_t len = sizeof(sndbuf); getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len ); fprintf( stderr, "sndbuf: set=%d get=%d\n", p.sndbuf, sndbuf ); if ( 0 != p.rcvbuf ) unistd::setsockopt( sock, SOL_SOCKET, SO_RCVBUF, p.rcvbuf ); sctp_initmsg init_params; memset( &init_params, 0, sizeof(init_params) ); init_params.sinit_num_ostreams = 1; init_params.sinit_max_instreams = 1; init_params.sinit_max_attempts = 3; init_params.sinit_max_init_timeo = 100; unistd::setsockopt( sock, SOL_SCTP, SCTP_INITMSG, init_params ); unistd::connect( sock, addr ); sctp_assoc_t assoc_id = 0; while ( assoc_id == 0 ) { std::vector<char> cmsg_buff( CMSG_SPACE( sizeof( sctp_sndrcvinfo ) ) ); std::vector<char> msg_buff( 8192 ); //TODO: struct iovec iov; memset( &iov, 0, sizeof(iov) ); iov.iov_base = msg_buff.data(); iov.iov_len = msg_buff.size(); struct msghdr hdr; memset( &hdr, 0, sizeof(hdr) ); hdr.msg_name = nullptr; hdr.msg_namelen = 0; hdr.msg_iov = &iov; hdr.msg_iovlen = 1; hdr.msg_control = cmsg_buff.data(); hdr.msg_controllen = cmsg_buff.size(); hdr.msg_flags = 0; ssize_t nrecv = 0; TEMP_FAILURE_RETRY( nrecv = recvmsg( sock, &hdr, 0 ) ); if ( 0 == nrecv ) raise( SIGTRAP ); if ( -1 == nrecv ) raise( SIGTRAP ); if ( hdr.msg_flags & MSG_NOTIFICATION ) { const sctp_notification& notify = *reinterpret_cast<const sctp_notification*>( hdr.msg_iov[0].iov_base ); switch ( notify.sn_header.sn_type ) { case SCTP_ASSOC_CHANGE: { const auto& sac = notify.sn_assoc_change; std::cout << " assoc_id=" << sac.sac_assoc_id << " error=" << sac.sac_error << " in=" << sac.sac_inbound_streams << " out=" << sac.sac_outbound_streams << std::endl; assoc_id = sac.sac_assoc_id; break; } case SCTP_REMOTE_ERROR: { const auto& sre = notify.sn_remote_error; printf( "^^^ remote_error: err=%hu len=%hu\n", ntohs(sre.sre_error), ntohs(sre.sre_length) ); return EXIT_FAILURE; } case SCTP_SHUTDOWN_EVENT: { printf( "^^^ SCTP_SHUTDOWN_EVENT\n" ); return EXIT_FAILURE; } } } } //int flags = fcntl( sock, F_GETFL, 0 ); //fcntl( sock, F_SETFL, flags | O_NONBLOCK ); const std::vector<char> msg = generate_message( p.msgsize ); struct iovec iov; iov.iov_base = const_cast<char*>( msg.data() ); iov.iov_len = msg.size(); std::vector<char> cmsg_buff( CMSG_SPACE( sizeof( sctp_sndrcvinfo ) ) ); struct mmsghdr mhdr; memset( &mhdr, 0, sizeof(mhdr) ); struct msghdr& hdr = mhdr.msg_hdr; hdr.msg_name = nullptr; hdr.msg_namelen = 0; hdr.msg_iov = &iov; hdr.msg_iovlen = 1; hdr.msg_flags = 0; hdr.msg_control = cmsg_buff.data(); hdr.msg_controllen = cmsg_buff.size(); cmsghdr* cmsg = CMSG_FIRSTHDR( &hdr ); cmsg->cmsg_level = IPPROTO_SCTP; cmsg->cmsg_type = SCTP_SNDRCV; cmsg->cmsg_len = CMSG_LEN( sizeof( sctp_sndrcvinfo ) ); sctp_sndrcvinfo& cmsg_data = *reinterpret_cast<sctp_sndrcvinfo*>( CMSG_DATA( cmsg ) ); cmsg_data.sinfo_stream = 0; cmsg_data.sinfo_ssn = 0; //ignored cmsg_data.sinfo_flags = SCTP_UNORDERED; cmsg_data.sinfo_ppid = 31337; cmsg_data.sinfo_context = 123456; cmsg_data.sinfo_timetolive = 0; cmsg_data.sinfo_tsn = 0; //ignored cmsg_data.sinfo_cumtsn = 0; //ignored cmsg_data.sinfo_assoc_id = assoc_id; std::vector<mmsghdr> mhdrs( p.batch, mhdr ); while ( p.count ) { const ssize_t count = std::min<uint64_t>( p.batch, p.count ); ssize_t nsend = 0; TEMP_FAILURE_RETRY( nsend = sendmmsg( sock, mhdrs.data(), count, 0 ) ); if ( 0 == nsend ) raise( SIGTRAP ); if ( -1 == nsend ) raise( SIGTRAP ); if ( count != nsend ) raise( SIGTRAP ); p.count -= count; } //raise( SIGTRAP ); sock.close(); return EXIT_SUCCESS; }