#include #include #include #include #include #include #include #include int main() { int si = -1; int so = -1; int se = -1; struct sockaddr_in ai{}; struct sockaddr_in ao{}; struct sockaddr_in ae{}; struct sockaddr_in am{}; socklen_t li = sizeof(ai); socklen_t lo = sizeof(ao); socklen_t le = sizeof(ae); socklen_t lm; pid_t pid = getpid(); struct sctp_event_subscribe ei{}; ai.sin_family = AF_INET; ai.sin_addr.s_addr = htonl(0x7F000000 | (pid & 0xFFFFFF)); ao.sin_family = AF_INET; ao.sin_addr.s_addr = htonl(0x7F000000 | (pid & 0xFFFFFF)); ae.sin_family = AF_INET; ae.sin_addr.s_addr = htonl(0x7F000000 | (pid & 0xFFFFFF)); si = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); if (si == -1) { perror("socket"); return 1; } so = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); if (so == -1) { perror("socket"); return 1; } se = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); if (se == -1) { perror("socket"); return 1; } if (bind(si, reinterpret_cast(&ai), sizeof(ai)) == -1) { perror("bind"); return 1; } if (bind(so, reinterpret_cast(&ao), sizeof(ao)) == -1) { perror("bind"); return 1; } if (bind(se, reinterpret_cast(&ae), sizeof(ae)) == -1) { perror("bind"); return 1; } if (getsockname(si, reinterpret_cast(&ai), &li) == -1) { perror("getsockname"); return 1; } if (getsockname(so, reinterpret_cast(&ao), &lo) == -1) { perror("getsockname"); return 1; } if (getsockname(se, reinterpret_cast(&ae), &le) == -1) { perror("getsockname"); return 1; } ei.sctp_association_event = 1; ei.sctp_data_io_event = 1; if (setsockopt(si, IPPROTO_SCTP, SCTP_EVENTS, &ei, sizeof(ei)) == -1) { perror("setsockopt"); return 1; } if (listen(si, 2) == -1) { perror("listen"); return 1; } if (connect(so, reinterpret_cast(&ai), lo) == -1) { perror("connect"); return 1; } if (connect(se, reinterpret_cast(&ai), le) == -1) { perror("connect"); return 1; } write(so, "o", 1); write(so, "OO", 2); write(so, "o", 1); write(so, "OO", 2); write(se, "e", 1); write(se, "EE", 2); write(se, "e", 1); write(se, "EE", 2); while (true) { char buf[4096] = { 0 }; struct sctp_sndrcvinfo info{}; int flags; int len; lm = sizeof(am); flags = 0; len = sctp_recvmsg(si, buf, sizeof(buf), reinterpret_cast(&am), &lm, &info, &flags); if (len == -1) { perror("sctp_recvmsg"); return 1; } std::cout << "flags " << flags << " assoc_id " << info.sinfo_assoc_id << " stream " << info.sinfo_stream << " port " << am.sin_port << " len " << len; if (!(flags & MSG_NOTIFICATION)) { if (len > 0) std::cout << " data "; for (int i = 0; i < len; i++ ) { std::cout << buf[i]; } } std::cout << std::endl; } return 0; }