1 /*
2 * This file is part of vban_emitter.
3 * Copyright (c) 2018 by Benoît Quiniou <quiniouben@yahoo.fr>
4 *
5 * vban_emitter is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * vban_emitter is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with vban_emitter. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <signal.h>
23 #include <getopt.h>
24 #include "vban/vban.h"
25 #include "common/version.h"
26 #include "common/socket.h"
27 #include "common/logger.h"
28
29 struct config_t
30 {
31 struct socket_config_t socket;
32 char stream_name[VBAN_STREAM_NAME_SIZE];
33 int bps;
34 int ident;
35 int format;
36 };
37
38 struct main_t
39 {
40 socket_handle_t socket;
41 char buffer[VBAN_PROTOCOL_MAX_SIZE];
42 };
43
usage()44 void usage()
45 {
46 printf("\nUsage: vban_sendtext [OPTIONS] MESSAGE\n\n");
47 printf("-i, --ipaddress=IP : MANDATORY. ipaddress to send stream to\n");
48 printf("-p, --port=PORT : MANDATORY. port to use\n");
49 printf("-s, --streamname=NAME : MANDATORY. streamname to use\n");
50 printf("-b, --bps=VALUE : Data bitrate indicator. default 0 (no special bitrate)\n");
51 //XXX give allowed value
52
53 printf("-n, --ident=VALUE : Subchannel identification. default 0\n");
54 printf("-f, --format=VALUE : Text format used. can be: 0 (ASCII), 1 (UTF8), 2 (WCHAR), 240 (USER). default 1\n");
55 printf("-l, --loglevel=LEVEL : Log level, from 0 (FATAL) to 4 (DEBUG). default is 1 (ERROR)\n");
56 printf("-h, --help : display this message\n\n");
57 }
58
get_options(struct config_t * config,int argc,char * const * argv)59 int get_options(struct config_t* config, int argc, char* const* argv)
60 {
61 int c = 0;
62 int ret = 0;
63
64 static const struct option options[] =
65 {
66 {"ipaddress", required_argument, 0, 'i'},
67 {"port", required_argument, 0, 'p'},
68 {"streamname", required_argument, 0, 's'},
69 {"bps", required_argument, 0, 'b'},
70 {"ident", required_argument, 0, 'n'},
71 {"format", required_argument, 0, 'f'},
72 {"loglevel", required_argument, 0, 'l'},
73 {"help", no_argument, 0, 'h'},
74 {0, 0, 0, 0 }
75 };
76
77 // default values
78 config->bps = 0;
79 config->ident = 0;
80 config->format = 1;
81 config->socket.direction = SOCKET_OUT;
82
83 /* yes, I assume config is not 0 */
84 while (1)
85 {
86 c = getopt_long(argc, argv, "i:p:s:b:n:f:l:h", options, 0);
87 if (c == -1)
88 break;
89
90 switch (c)
91 {
92 case 'i':
93 strncpy(config->socket.ip_address, optarg, SOCKET_IP_ADDRESS_SIZE-1);
94 break;
95
96 case 'p':
97 config->socket.port = atoi(optarg);
98 break;
99
100 case 's':
101 strncpy(config->stream_name, optarg, VBAN_STREAM_NAME_SIZE-1);
102 break;
103
104 case 'b':
105 config->bps = atoi(optarg);
106 break;
107
108 case 'n':
109 config->ident = atoi(optarg);
110 break;
111
112 case 'f':
113 config->format = atoi(optarg);
114 break;
115
116 case 'l':
117 logger_set_output_level(atoi(optarg));
118 break;
119
120 case 'h':
121 default:
122 usage();
123 return 1;
124 }
125
126 if (ret)
127 {
128 return ret;
129 }
130 }
131
132 /** check if we got all arguments */
133 if ((config->socket.ip_address[0] == 0)
134 || (config->socket.port == 0)
135 || (config->stream_name[0] == 0))
136 {
137 logger_log(LOG_FATAL, "Missing ip address, port or stream name");
138 usage();
139 return 1;
140 }
141
142 if (optind == argc)
143 {
144 logger_log(LOG_FATAL, "Missing message argument");
145 usage();
146 return 1;
147 }
148 else if (optind < argc - 1)
149 {
150 logger_log(LOG_FATAL, "Too many arguments");
151 usage();
152 return 1;
153 }
154
155 return 0;
156 }
157
158
main(int argc,char * const * argv)159 int main(int argc, char* const* argv)
160 {
161 int ret = 0;
162 struct config_t config;
163 struct main_t main_s;
164 char const* msg = 0;
165 size_t len = 0;
166 struct VBanHeader* const hdr = (struct VBanHeader*)&main_s.buffer;
167
168 printf("%s version %s\n\n", argv[0], VBAN_VERSION);
169
170 memset(&config, 0, sizeof(struct config_t));
171 memset(&main_s, 0, sizeof(struct main_t));
172
173 ret = get_options(&config, argc, argv);
174 if (ret != 0)
175 {
176 return ret;
177 }
178
179 msg = argv[argc-1];
180 len = strlen(msg);
181 if (len > VBAN_DATA_MAX_SIZE-1)
182 {
183 logger_log(LOG_FATAL, "Message too long. max lenght is %d", VBAN_DATA_MAX_SIZE-1);
184 usage();
185 return 1;
186 }
187
188 strncpy((char*)&main_s.buffer + sizeof(struct VBanHeader), msg, VBAN_DATA_MAX_SIZE-1);
189
190 ret = socket_init(&main_s.socket, &config.socket);
191 if (ret != 0)
192 {
193 return ret;
194 }
195
196 hdr->vban = VBAN_HEADER_FOURC;
197 hdr->format_SR = config.bps | VBAN_PROTOCOL_TXT;
198 hdr->format_nbs = 0;
199 hdr->format_nbc = config.ident;
200 hdr->format_bit = config.format;
201 strncpy(hdr->streamname, config.stream_name, VBAN_STREAM_NAME_SIZE);
202 hdr->nuFrame = 0;
203
204 logger_log(LOG_DEBUG, "%s: packet is vban: %u, sr: %d, nbs: %d, nbc: %d, bit: %d, name: %s, nu: %u, msg: %s",
205 __func__, hdr->vban, hdr->format_SR, hdr->format_nbs, hdr->format_nbc, hdr->format_bit, hdr->streamname, hdr->nuFrame, (char*)&main_s.buffer + sizeof(struct VBanHeader));
206
207 ret = socket_write(main_s.socket, main_s.buffer, len + sizeof(struct VBanHeader));
208
209 socket_release(&main_s.socket);
210
211 return ret;
212 }
213
214