Welcome Guest ( Log In | Register )

> Access AMIP socket server from *nix
uplate
post Oct 10 2007, 02:03 AM
Post #1


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



Hi, I am interested in trying to access AMIP from *nix. It appears that AMIP server creates a TCP socket connection that should be able to be accessed remotely. Can you give some indication on how this could be done?

I've tried with socket and telnet, but both indicate that the AMIP hosting machine refuses the connection.

My setup:

[WIN]
AMIP Server:40581

[NIX]
Client access:
`telnet WIN 40581`
`socket WIN 40581`

Thanks
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
2 Pages V  1 2 >  
Reply to this topicStart new topic
Replies(1 - 19)
Serge
post Oct 10 2007, 09:01 AM
Post #2


AMIP Developer
***

Group: Root Admin
Posts: 935
Joined: 12-March 06
Member No.: 1



AMIP uses specific protocol, application which connects must be created using the RCF for C++.

In AMIP API/Server settings set the correct bind address (0.0.0.0 for all interfaces, otherwise, AMIP will listen only on 127.0.0.1, thus making it impossible to connect from another machines).

AMIP's RCF interface IDL:

CODE

RCF_BEGIN(MyService, "MyService");

RCF_METHOD_V3(void, exec, std::string, std::string, std::string);
RCF_METHOD_R2(std::string, eval, std::string, std::string);
RCF_METHOD_R0(std::string, ping);
RCF_METHOD_V5(void, add_event_listener, std::string, int, int, UINT, UINT);
RCF_METHOD_V2(void, remove_event_listener, std::string, int);
RCF_METHOD_R0(std::vector<std::string>, get_pltitles);

RCF_END(MyService);


Current AMIP version is built with RCF 0.4 and will not work with 0.9, the next version will be build with RCF 0.9c.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Oct 15 2007, 12:40 PM
Post #3


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



::phew::..finally got boost/asio/rcf compiled and working on FreeBSD, can't wait to start writing clients for amip/server.

thank so much for your help so far!


max
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Oct 15 2007, 11:39 PM
Post #4


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



OK, so I've tried writing a basic program to ping AMIP:
CODE

#include <iostream>
#include <string>

#include <RCF/Idl.hpp>
#include <RCF/TcpEndpoint.hpp>
#include <RCF/Exception.hpp>

RCF_BEGIN(Amip, "Amip");
        RCF_METHOD_R0(std::string, ping);
RCF_END(Amip);

int main()
{
        try
        {
          RcfClient<Amip> amipClient( RCF::TcpEndpoint( "192.168.0.203", 60333 ) );
          std::cout << amipClient.ping() << std::endl;
        }
        catch( RCF::Exception ex )
        {
          std::cout << ex.what() << std::endl;
        }
        return 0;
}


When I run the program, I get the following error:
CODE

[uplate@~/devel/src/amip-client]> ./amipclient
Marshal.cpp(67): void RCF::IDL::doInReturnValue(RCF::ClientStub&, RCF::SerializationProtocolIn&, RCF::SerializationProtocolOut&, bool): : Thread-id=134774784 : Timestamp(ms)=63383011: THROW : ClientTransportException: server response timed out: totalTimeoutMs=10000, typeid(connection)=N3RCF22TcpAsioClientTransportE,


I'm sure that the amip server is up and running on 192.168.0.203:60333 because I can telnet to it..is my code bad or is this a problem with my installation of RCF/asio do you think?

Thanks,
Max
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Serge
post Oct 15 2007, 11:43 PM
Post #5


AMIP Developer
***

Group: Root Admin
Posts: 935
Joined: 12-March 06
Member No.: 1



AMIP on Windows is not using ASIO for RCF, but the native sockets, so it could be a problem. I'll try contacting RCF developer with this question.

What kind of client do you want to write and what for?
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Oct 16 2007, 12:18 AM
Post #6


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



Thank you for looking into this for me. I could help you with anything you'd like if you want help using asio on windows, although I'm not much of a programmer.

This is kind of a fun little project for me to do, so the program I write could be as simple as an executable which pulls the song information from AMIP, or an irssi plugin which implements greater functionality. Myself, and a certain percentage of the populace, use Windows as a desktop, but PuTTY+irssi for chat. This would be great for us, as AMIP appears to be quite powerful. Other solutions I've tried were having another Winamp plugin FTP a file with song information to my server, but this is very ugly in comparison with the solution I have in mind.

I guess you are the person who responded to my post on codeproject :-)

I will try to write a simple server program on windows using RCF/ASIO, and see if this will allow cross-platform TCP/socket connection if that would help you diagnose...
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Serge
post Oct 16 2007, 10:22 AM
Post #7


AMIP Developer
***

Group: Root Admin
Posts: 935
Joined: 12-March 06
Member No.: 1



Here is AMIP compiled with RCF 0.9: gen_irc.dll.
Replace the original in Winamp/Plugins or if using another player, rename to amip.dll.

Compile your client with RCF 0.9 and see if it helps. Don't use BOOST serialization (use RCF_USE_SF_SERIALIZATION).

Here is AMIP SDK compiled with RCF 0.9. You can try the samples on the Windows machine to see if it works.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Oct 16 2007, 11:53 PM
Post #8


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



IT WORKED!

CODE

[uplate@~/devel/src/amip-client]> ./amipclient
!!! - Bend Over Beethoven
[uplate@~/devel/src/amip-client]> ./amipclient
Karate Kid - You're the Best
[uplate@~/devel/src/amip-client]>


Thanks for you time and effort, this is so great :-)
Max
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Oct 20 2007, 02:20 AM
Post #9


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



ive been working on an irssi module, and it's been kinda successful =-). see the attached screenshot.


if it's ok with you, i'd like to begin public development, on sourceforge or something, so people can help me by contributing/testing. i'd like to call the project NARC, for Nix-Amip Remote Control.


Attached thumbnail(s)
Attached Image
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Serge
post Oct 20 2007, 11:27 AM
Post #10


AMIP Developer
***

Group: Root Admin
Posts: 935
Joined: 12-March 06
Member No.: 1



Looks nice, thanks for your efforts.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Oct 21 2007, 02:22 AM
Post #11


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



Here's another picture.

Looking at the IDL, I realize I don't really know how a few of the functions work.

CODE

RCF_METHOD_V3(void, exec, std::string, std::string, std::string);
RCF_METHOD_V5(void, add_event_listener, std::string, int, int, UINT, UINT);
RCF_METHOD_V2(void, remove_event_listener, std::string, int);


What three arguments does `exec` accept? 'command',..? ac.h doesn't make it clear to me what ought to be provided to client.exec( ... ), beyond the actual command.

I understand how the event listeners are supposed to work from the perspective of setting up callbacks, but I don't have any idea what arguments are to provided to the IDL functions.

Thanks,
Max


Attached thumbnail(s)
Attached Image
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Serge
post Oct 21 2007, 11:35 AM
Post #12


AMIP Developer
***

Group: Root Admin
Posts: 935
Joined: 12-March 06
Member No.: 1



Using listeners is a bit complicated and requires a server on your side to accept connections with different IDL. It's not needed if you just want to use exec/eval commands.

Exec command executes AMIP API command (see the manual for the list of the commands). 3 parameters is a legacy thing from the DDE API used before.

Actually you need to split the API command into 3 strings by spaces and pass them to this function. If there are less than 3 words in the string, pass empty string.

Like for "control pause"

client->exec("control", "pause", "");

If you need more information, I can provide you sources of ac.dll so that you see how it works (contact me by mail). Note that ac.dll also includes mIRC API, so the code is not very clean.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Oct 24 2007, 01:51 AM
Post #13


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



thanks for the information, and the source has been quite helpful :-). ac_exec( one, two, three) is now working for this program.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Nov 2 2007, 01:36 AM
Post #14


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



Hey again,

so i'm a little stuck trying to implement any kind of ClientService. I know that AMIP on my windows machine is properly transmitting commands and events, because when i run a socket tool, i get output:
CODE

[uplate@~/devel/src/narc/src]> socket -sl 60334
ClientServiceC//describe $active np: !!! - Heart Of Hearts [06:02m/320kbps/44kHz]

if i run a program to set up an event listener, i also see stuff appear when i hit play or pause in winamp, or send a play/pause command from my *nix box using MyService IDL.

however, when i try to run the following code i always get a core dump. it starts up fine, but then segfaults when i take any action in amip (play/pause/change song/etc...):

CODE

/*
* C++ headers
*/
#include <RCF/Idl.hpp>
#include <RCF/RcfServer.hpp>
#include <RCF/TcpEndpoint.hpp>
#include <iostream>

/* AMIP IDLs */
#include "amip/ClientService.hpp"

class NarcService
{
  public:
  void exec( std::string cmd )
  {
    std::cout << "Got exec" << std::endl;
  }
  void event( unsigned int code )
  {
    std::cout << "Got event" << std::endl;
  }
};

int main()
{
  NarcService narcService;
  RCF::RcfServer server(RCF::TcpEndpoint(60334));
  server.bind<ClientService>(narcService);
  server.startInThisThread();
  return 0;
}


then this occurs when i create an event from winamp or a MyService program:
CODE

[uplate@~/devel/src/narc/src]> ./narcserver
zsh: segmentation fault (core dumped)  ./narcserver


here is the gdb backtrace:
CODE

Starting program: /usr/home/uplate/devel/src/narc/src/narcserver
warning: Unable to get location for thread creation breakpoint: generic error
[New LWP 100040]
[New Thread 0x8093000 (LWP 100086)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x8093000 (LWP 100086)]
0x2825cee9 in RCF::MethodInvocationRequest::decodeFiltered ()
   from /usr/local/lib/librcf.so
(gdb) bt
#0  0x2825cee9 in RCF::MethodInvocationRequest::decodeFiltered ()
   from /usr/local/lib/librcf.so
#1  0x28258c22 in RCF::MethodInvocationRequest::decodeRequest ()
   from /usr/local/lib/librcf.so
#2  0x28274164 in RCF::RcfServer::onReadCompleted () from /usr/local/lib/librcf.so
#3  0x2828eed8 in RCF::TcpServerTransport::cycleRead ()
   from /usr/local/lib/librcf.so
#4  0x2828f96e in RCF::TcpServerTransport::cycle () from /usr/local/lib/librcf.so
#5  0x2828fdc8 in RCF::TcpServerTransport::cycleTransportAndServer ()
   from /usr/local/lib/librcf.so
#6  0x28303f06 in boost::_mfi::mf3<bool, RCF::TcpServerTransport, RCF::RcfServer&, int, bool const volatile&>::operator() () from /usr/local/lib/librcf.so
#7  0x28302eb6 in boost::_bi::list4<boost::_bi::value<RCF::TcpServerTransport*>, boost::reference_wrapper<RCF::RcfServer>, boost::arg<1> (*)(), boost::arg<2> (*)()>::operator()<bool, boost::_mfi::mf3<bool, RCF::TcpServerTransport, RCF::RcfServer&, int, bool const volatile&>, boost::_bi::list3<int&, bool const volatile&, bool&> > ()
   from /usr/local/lib/librcf.so
#8  0x283003b5 in boost::_bi::bind_t<bool, boost::_mfi::mf3<bool, RCF::TcpServerTransport, RCF::RcfServer&, int, bool const volatile&>, boost::_bi::list4<boost::_bi::value<RCF::TcpServerTransport*>, boost::reference_wrapper<RCF::RcfServer>, boost::arg<1> (*)(), boost::arg<2> (*)()> >::operator()<int, bool const volatile, bool> ()
   from /usr/local/lib/librcf.so
---Type <return> to continue, or q <return> to quit---
#9  0x282fdf67 in boost::detail::function::function_obj_invoker3<boost::_bi::bind_t<bool, boost::_mfi::mf3<bool, RCF::TcpServerTransport, RCF::RcfServer&, int, bool const volatile&>, boost::_bi::list4<boost::_bi::value<RCF::TcpServerTransport*>, boost::reference_wrapper<RCF::RcfServer>, boost::arg<1> (*)(), boost::arg<2> (*)()> >, bool, int, bool const volatile&, bool>::invoke () from /usr/local/lib/librcf.so
#10 0x282bf412 in boost::function3<bool, int, bool const volatile&, bool, std::allocator<boost::function_base> >::operator() () from /usr/local/lib/librcf.so
#11 0x28272602 in RCF::RcfServer::cycle () from /usr/local/lib/librcf.so
#12 0x2826ae0a in RCF::repeatCycleServer () from /usr/local/lib/librcf.so
#13 0x28272204 in RCF::RcfServer::startInThisThread () from /usr/local/lib/librcf.so
#14 0x28271fad in RCF::RcfServer::startInThisThread () from /usr/local/lib/librcf.so
#15 0x0805ba50 in main () at narc_server.cpp:30
(gdb)


i realize you do things a little differently in your code, with templating, threads, queues and stuff. that is a little advanced for me right now, so i'm trying to build my way up using the examples on the RCF website.


thanks,
max
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Nov 3 2007, 02:56 AM
Post #15


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



Hey Serge,

Ignore the last email, it was a problem of needing to have the libs and source built with BOOST_ASIO. I got that solved, and now I have a 95% working server program. Using the code I listed above, I now get the following when I run the following test program:
CODE

/*
* C++ headers
*/
#include <RCF/ClientStub.hpp>
#include <RCF/Idl.hpp>
#include <RCF/RcfServer.hpp>
#include <RCF/TcpEndpoint.hpp>
#include <SF/vector.hpp>
#include <iostream>

/* AMIP IDLs */
#include "amip/MyService.hpp"
#include "amip/ClientService.hpp"

/*
* C headers
*/
#ifdef __cplusplus
extern "C" {
#include <unistd.h>
}
#endif

int main()
{
   RcfClient<ClientService> server_test(RCF::TcpEndpoint("localhost", 60334));
   server_test.exec("hello");
   return 0;
}


Run server program, followed by above test.
CODE

[uplate@~/devel/src/narc/src]> ./narcserver
Got exec


However, when I try change a song in AMIP, the server program does not respond. This confuses me, because before, when I had a server program built without ASIO, the server program would segfault when I changed a song in AMIP. Now it seems as if the server program does not even get a connection from AMIP.

It is clear to me that, in the case where the server program runs without ASIO, it binds to *:60334, whereas when I compile with ASIO, it binds to 127.0.0.1:60334, regardless of what I set "host" to in RCF::TcpEndpoint. I have verified this by running `sockstat -l4` in either case. I realize that this appears to be an RCF issue, but I thought I'd post it here for the benefit of anyone else trying this stuff out, or in case you'd encountered anything like this.

Max
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Nov 3 2007, 05:28 AM
Post #16


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



Was a bug in RCF, author gave me a fix. Now I have totally functional amip client on *NIX :-).
CODE

[uplate@~/devel/src/narc/src]> ./narcserver
Got exec: //describe $active np: Black Dice - Bottom Feeder [02:50m/320kbps/44kHz]
Got event: 2
Got event: 1
Got event: 4
Got event: 1
Got event: 128
Got exec: //describe $active np: Black Dice - Scavenger [05:16m/320kbps/44kHz]
Got event: 128
Got exec: //describe $active np: Black Dice - Drool [05:51m/320kbps/44kHz]
Got event: 128
Got exec: //describe $active np: Black Dice - Scavenger [05:16m/320kbps/44kHz]
Got event: 16
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Nov 4 2007, 05:24 PM
Post #17


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



Implemented ClientService mechanism as an irssi plugin. BOOST_THREADS don't seem to play nicely in irssi, I get failure to allocate thread resources. So I'm forced to use POSIX threads (pthreads), which, while probably not as safe, is definitely doable since I'm only using a single thread for the service. I basically copied your GenericServer word for word, replacing the windows thread stuff with unix thread stuff. I think I basically have it down, although I don't really understand a few things.

(1) Mutexes. No idea what these are, I'll have to read up.
(2) The mechanism through which a C++ member function is passed as a function pointer argument to a C function.

Regarding (2), I was pulling my hair out trying to figure out how to do this, when I decided to try it like you did. I figured your method wouldn't work on *nix, thinking it was MS specific, but it worked great. You are a genius sir tongue.gif.

Here are the salient features of my implementation.
CODE

extern "C" {
#include <pthread.h>
void *thread_start(void *);
}

template<typename InterfaceT, typename ImplementationT>
class NarcService {
public:
  NarcService() { ... }
  void start() { pthread_create( &serverThread, NULL, thread_start, this ); }
private:
  void joinServerThread() { pthread_join(serverThread,NULL); }
  virtual void run() { server->startInThisThread(boost::bind(
                                    &NarcService::joinServerThread,this)); }
  static void *thread_start( void *obj )
  { (static_cast<NarcService *>(obj))->run(); }
};



Attached thumbnail(s)
Attached Image
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Nov 27 2007, 03:06 AM
Post #18


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



Now have most of the major functionality of the AMIP socket server available to my Irssi plugin.
+ ping, eval, exec, add/remove_event_listener
+ receive output from AMIP through service

I'm getting ready to release a "demo" version to sourceforge.net.
I was planning on releasing as GPL, but since I'm using two pieces of code from the SDK (MyService.hpp and ClientService.hpp), I thought I'd ask your opinion on that first.


Attached thumbnail(s)
Attached Image
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Serge
post Nov 27 2007, 08:12 AM
Post #19


AMIP Developer
***

Group: Root Admin
Posts: 935
Joined: 12-March 06
Member No.: 1



I don't mind, please feel free to release it.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
uplate
post Dec 22 2007, 05:46 PM
Post #20


Member
**

Group: Members
Posts: 21
Joined: 10-October 07
Member No.: 391



Is it OK if I include the gen_irc.dll *compiled with RCF 0.9c that you provided) in the project distribution? If not, can I instruct users to download it from the link?

Thanks
Max
User is offlineProfile CardPM
Go to the top of the page
+Quote Post

2 Pages V  1 2 >
Reply to this topicStart new topic
6 User(s) are reading this topic (6 Guests and 0 Anonymous Users)
0 Members: