1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
#ifndef _WIN32
#include <arpa/inet.h>
#include <netdb.h>
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <string>
#include <sstream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <srt.h>
using namespace std;
string ShowChar(char in)
{
if (in >= 32 && in < 127)
return string(1, in);
ostringstream os;
os << "<" << hex << uppercase << int(in) << ">";
return os.str();
}
int main(int argc, char* argv[])
{
if ((argc != 4) || (0 == atoi(argv[2])))
{
cout << "usage: sendmsg server_ip server_port source_filename" << endl;
return -1;
}
// Use this function to initialize the UDT library
srt_startup();
srt_setloglevel(srt_logging::LogLevel::debug);
struct addrinfo hints, *peer;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
SRTSOCKET fhandle = srt_create_socket();
// SRT requires that third argument is always SOCK_DGRAM. The Stream API is set by an option,
// although there's also lots of other options to be set, for which there's a convenience option,
// SRTO_TRANSTYPE.
SRT_TRANSTYPE tt = SRTT_FILE;
srt_setsockopt(fhandle, 0, SRTO_TRANSTYPE, &tt, sizeof tt);
bool message_mode = true;
srt_setsockopt(fhandle, 0, SRTO_MESSAGEAPI, &message_mode, sizeof message_mode);
if (0 != getaddrinfo(argv[1], argv[2], &hints, &peer))
{
cout << "incorrect server/peer address. " << argv[1] << ":" << argv[2] << endl;
return -1;
}
// Connect to the server, implicit bind.
if (SRT_ERROR == srt_connect(fhandle, peer->ai_addr, peer->ai_addrlen))
{
int rej = srt_getrejectreason(fhandle);
cout << "connect: " << srt_getlasterror_str() << ":" << srt_rejectreason_str(rej) << endl;
return -1;
}
freeaddrinfo(peer);
string source_fname = argv[3];
bool use_filelist = false;
if (source_fname[0] == '+')
{
use_filelist = true;
source_fname = source_fname.substr(1);
}
istream* pin;
ifstream fin;
if (source_fname == "-")
{
pin = &cin;
}
else
{
fin.open(source_fname.c_str());
pin = &fin;
}
// The syntax is:
//
// 1. If the first character is +, it's followed by TTL in milliseconds.
// 2. Otherwise the first number is the ID, followed by a space, to be filled in first 4 bytes.
// 3. Rest of the characters, up to the end of line, should be put into a solid block and sent at once.
int status = 0;
int ordinal = 1;
int lpos = 0;
for (;;)
{
string line;
int32_t id = 0;
int ttl = -1;
getline(*pin, (line));
if (pin->eof())
break;
// Interpret
if (line.size() < 2)
continue;
if (use_filelist)
{
// The line should contain [+TTL] FILENAME
char fname[1024] = "";
if (line[0] == '+')
{
int nparsed = sscanf(line.c_str(), "+%d %n%1000s", &ttl, &lpos, fname);
if (nparsed != 2)
{
cout << "ERROR: syntax error in input (" << nparsed << " parsed pos=" << lpos << ")\n";
status = SRT_ERROR;
break;
}
line = fname;
}
ifstream ifile (line);
id = ordinal;
++ordinal;
if (!ifile.good())
{
cout << "ERROR: file '" << line << "' cannot be read, skipping\n";
continue;
}
line = string(istreambuf_iterator<char>(ifile), istreambuf_iterator<char>());
}
else
{
int lpos2 = 0;
int nparsed = 0;
if (line[0] == '+')
{
nparsed = sscanf(line.c_str(), "+%d %d %n%*s", &ttl, &id, &lpos2);
if (nparsed != 2)
{
cout << "ERROR: syntax error in input (" << nparsed << " parsed pos=" << lpos2 << ")\n";
status = SRT_ERROR;
break;
}
}
else
{
nparsed = sscanf(line.c_str(), "%d %n%*s", &id, &lpos2);
if (nparsed != 1)
{
cout << "ERROR: syntax error in input (" << nparsed << " parsed pos=" << lpos2 << ")\n";
status = SRT_ERROR;
break;
}
}
}
union
{
char chars[4];
int32_t intval;
} first4;
first4.intval = htonl(id);
vector<char> input;
copy(first4.chars, first4.chars+4, back_inserter(input));
copy(line.begin() + lpos, line.end(), back_inserter(input));
// CHECK CODE
// cout << "WILL SEND: TTL=" << ttl << " ";
// transform(input.begin(), input.end(),
// ostream_iterator<string>(cout), ShowChar);
// cout << endl;
int nsnd = srt_sendmsg(fhandle, &input[0], input.size(), ttl, false);
if (nsnd == SRT_ERROR)
{
cout << "SRT ERROR: " << srt_getlasterror_str() << endl;
status = SRT_ERROR;
break;
}
}
srt_close(fhandle);
// Signal to the SRT library to clean up all allocated sockets and resources.
srt_cleanup();
return status;
}
|