example_tcp_echo_server.c
/*
* Copyright (C) 2012 Steve Harris, Stephen Sinclair
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* $Id$
*/
/* Run this program in one terminal with no arguments,
* $ ./example_tcp_echo_server
* and in another terminal with argument 1,
* $ ./example_tcp_echo_server 1
* Now watch the /test message ping back and forth a few times!
*/
#include <stdio.h>
#include <stdlib.h>
#ifndef WIN32
#include <unistd.h>
#include <sys/time.h>
#endif
#include <signal.h>
#include "lo/lo.h"
int done = 0;
int count = 0;
void error(int num, const char *m, const char *path);
int echo_handler(const char *path, const char *types, lo_arg ** argv,
int argc, lo_message data, void *user_data);
int quit_handler(const char *path, const char *types, lo_arg ** argv,
int argc, lo_message data, void *user_data);
void ctrlc(int sig)
{
done = 1;
}
int main(int argc, char *argv[])
{
const char *port = "7770";
int do_send = 0;
if (argc > 1 && argv[1][0]=='1') {
do_send = 1;
port = "7771";
}
/* start a new server on port 7770 */
lo_server_thread st = lo_server_thread_new_with_proto(port, LO_TCP, error);
if (!st) {
printf("Could not create server thread.\n");
exit(1);
}
lo_server s = lo_server_thread_get_server(st);
/* add method that will match the path /quit with no args */
lo_server_thread_add_method(st, "/quit", "", quit_handler, NULL);
/* add method that will match any path and args */
lo_server_thread_add_method(st, NULL, NULL, echo_handler, s);
lo_server_thread_start(st);
signal(SIGINT,ctrlc);
printf("Listening on TCP port %s\n", port);
lo_address a = 0;
if (do_send) {
a = lo_address_new_with_proto(LO_TCP, "localhost", "7770");
if (!a) {
printf("Error creating destination address.\n");
exit(1);
}
int r = lo_send_from(a, s, LO_TT_IMMEDIATE, "/test", "ifs",
1, 2.0f, "3");
if (r < 0)
printf("Error sending initial message.\n");
if (a) lo_address_free(a);
a = 0;
}
while (!done) {
#ifdef WIN32
Sleep(1);
#else
sleep(1);
#endif
}
lo_server_thread_free(st);
return 0;
}
void error(int num, const char *msg, const char *path)
{
printf("liblo server error %d in path %s: %s\n", num, path, msg);
fflush(stdout);
}
/* catch any incoming messages, display them, and send them
* back. */
int echo_handler(const char *path, const char *types, lo_arg ** argv,
int argc, lo_message data, void *user_data)
{
int i;
lo_message m = (lo_message)data;
lo_address a = lo_message_get_source(m);
lo_server s = (lo_server)user_data;
const char *host = lo_address_get_hostname(a);
const char *port = lo_address_get_port(a);
count ++;
#ifdef WIN32
Sleep(1);
#else
sleep(1);
#endif
printf("path: <%s>\n", path);
for (i = 0; i < argc; i++) {
printf("arg %d '%c' ", i, types[i]);
lo_arg_pp((lo_type)types[i], argv[i]);
printf("\n");
}
if (!a) {
printf("Couldn't get message source, quitting.\n");
done = 1;
return 0;
}
int r = lo_send_message_from(a, s, path, m);
if (r < 0)
printf("Error sending back message, socket may have closed.\n");
else
printf("Sent message back to %s:%s.\n", host, port);
if (count >= 3) {
printf("Got enough messages, quitting.\n");
done = 1;
}
return 0;
}
int quit_handler(const char *path, const char *types, lo_arg ** argv,
int argc, lo_message data, void *user_data)
{
done = 1;
printf("quitting\n\n");
fflush(stdout);
return 0;
}
lo_type
lo_type
An enumeration of the OSC types liblo can send and receive.
Definition lo_osc_types.h:61
lo_address_free
void lo_address_free(lo_address t)
Free the memory used by the lo_address object.
lo_send_from
int lo_send_from(lo_address targ, lo_server from, lo_timetag ts, const char *path, const char *type,...)
Send a OSC formatted message to the address specified, from the same socket as the specified server.
lo_address_new_with_proto
lo_address lo_address_new_with_proto(int proto, const char *host, const char *port)
Declare an OSC destination, given IP address and port number, specifying protocol.
LO_TT_IMMEDIATE
#define LO_TT_IMMEDIATE
A timetag constant representing "now".
Definition lo_osc_types.h:151
lo_address_get_hostname
const char * lo_address_get_hostname(lo_address a)
Return the hostname of a lo_address object.
lo_message_get_source
lo_address lo_message_get_source(lo_message m)
Returns the source (lo_address) of an incoming message.
lo_send_message_from
int lo_send_message_from(lo_address targ, lo_server serv, const char *path, lo_message msg)
Send a lo_message object to target targ from address of serv.
lo_address_get_port
const char * lo_address_get_port(lo_address a)
Return the port/service name of a lo_address object.
lo_arg_pp
void lo_arg_pp(lo_type type, void *data)
Pretty-print a set of typed arguments.
lo.h
lo_server_thread_start
int lo_server_thread_start(lo_server_thread st)
Start the server thread.
lo_server_thread_new_with_proto
lo_server_thread lo_server_thread_new_with_proto(const char *port, int proto, lo_err_handler err_h)
Create a new server thread to handle incoming OSC messages, specifying protocol.
lo_server_thread_get_server
lo_server lo_server_thread_get_server(lo_server_thread st)
Return the lo_server for a lo_server_thread.
lo_server_thread_free
void lo_server_thread_free(lo_server_thread st)
Free memory taken by a server thread.
lo_server_thread_add_method
lo_method lo_server_thread_add_method(lo_server_thread st, const char *path, const char *typespec, lo_method_handler h, const void *user_data)
Add an OSC method to the specifed server thread.
lo_server
struct lo_server_ * lo_server
An object representing an instance of an OSC server.
Definition lo_types.h:85
lo_address
struct lo_address_ * lo_address
A reference to an OSC service.
Definition lo_types.h:45
lo_message
struct lo_message_ * lo_message
A low-level object used to represent messages passed over OSC.
Definition lo_types.h:60
lo_server_thread
struct lo_server_thread_ * lo_server_thread
An object representing a thread containing an OSC server.
Definition lo_types.h:92
lo_arg
Union used to read values from incoming messages.
Definition lo_osc_types.h:104