I am writing c++ code (but my example is straight c) to talk to an AdaFruit Servo Motor Pi Hat, which uses the I2C bus to communicate with the Pi. I'm having a problem when trying to use the ioctl I2C_RDWR mechanism. I am getting a 'Bad Address' status back from the call. It doesn't matter what address I give it (the hat answers to 0x40, though), it always fails. I've boiled the code down into a short module, which is self contained. This is my first post to this site, so if I've done any faux pas, please forgive me.
When I run the attached code, I get the following response:
I2C_FUNC_I2C OK
I2C_FUNC_10BIT_ADDR
I2C_FUNC_PROTOCOL_MANGLING
I2C_FUNC_SMBUS_QUICK OK
I2C_FUNC_SMBUS_READ_BYTE OK
I2C_FUNC_SMBUS_WRITE_BYTE OK
I2C_FUNC_SMBUS_READ_BYTE_DATA OK
I2C_FUNC_SMBUS_WRITE_BYTE_DATA OK
I2C_FUNC_SMBUS_READ_WORD_DATA OK
I2C_FUNC_SMBUS_WRITE_WORD_DATA OK
I2C_FUNC_SMBUS_PROC_CALL OK
I2C_FUNC_SMBUS_READ_BLOCK_DATA
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA OK
I2C_FUNC_SMBUS_READ_I2C_BLOCK OK
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK OK
Write failed: Bad address
My Pi is a model B, version 2. I have enabled the i2c system and can see the i2c device:
crw-rw-rw- 1 root i2c 89, 1 Aug 31 23:02 i2c-1
Any help would be appreciated.
The code follows:
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
int main() {
int file;
int devAddr = 0x40;
int status;
uint32_t funcs;
uint8_t data = 0xAA;
struct i2c_rdwr_ioctl_data request;
struct i2c_msg ioctlMsg[1];
file = open("/dev/i2c-1", O_RDWR);
if(file < 0) {
perror("could not open device");
return 1;
}
status = ioctl(file, I2C_FUNCS, &funcs);
if(status < 0) {
perror("could not get funcs");
return 3;
}
fprintf(stderr, "\nI2C_FUNC_I2C ");
if ( I2C_FUNC_I2C & funcs) fprintf(stderr, "\t\t\t\tOK");
fprintf(stderr, "\nI2C_FUNC_10BIT_ADDR ");
if ( I2C_FUNC_10BIT_ADDR & funcs) fprintf(stderr, "\t\t\tOK");
fprintf(stderr, "\nI2C_FUNC_PROTOCOL_MANGLING ");
if ( I2C_FUNC_PROTOCOL_MANGLING & funcs) fprintf(stderr, "\tOK");
fprintf(stderr, "\nI2C_FUNC_SMBUS_QUICK ");
if ( I2C_FUNC_SMBUS_QUICK & funcs) fprintf(stderr, "\t\t\tOK");
fprintf(stderr, "\nI2C_FUNC_SMBUS_READ_BYTE ");
if ( I2C_FUNC_SMBUS_READ_BYTE & funcs) fprintf(stderr, "\t\tOK");
fprintf(stderr, "\nI2C_FUNC_SMBUS_WRITE_BYTE ");
if ( I2C_FUNC_SMBUS_WRITE_BYTE & funcs) fprintf(stderr, "\t\tOK");
fprintf(stderr, "\nI2C_FUNC_SMBUS_READ_BYTE_DATA ");
if ( I2C_FUNC_SMBUS_READ_BYTE_DATA & funcs) fprintf(stderr, "\t\tOK");
fprintf(stderr, "\nI2C_FUNC_SMBUS_WRITE_BYTE_DATA ");
if ( I2C_FUNC_SMBUS_WRITE_BYTE_DATA & funcs) fprintf(stderr, "\t\tOK");
fprintf(stderr, "\nI2C_FUNC_SMBUS_READ_WORD_DATA ");
if ( I2C_FUNC_SMBUS_READ_WORD_DATA & funcs) fprintf(stderr, "\t\tOK");
fprintf(stderr, "\nI2C_FUNC_SMBUS_WRITE_WORD_DATA ");
if ( I2C_FUNC_SMBUS_WRITE_WORD_DATA & funcs) fprintf(stderr, "\t\tOK");
fprintf(stderr, "\nI2C_FUNC_SMBUS_PROC_CALL ");
if ( I2C_FUNC_SMBUS_PROC_CALL & funcs) fprintf(stderr, "\t\tOK");
fprintf(stderr, "\nI2C_FUNC_SMBUS_READ_BLOCK_DATA ");
if ( I2C_FUNC_SMBUS_READ_BLOCK_DATA & funcs) fprintf(stderr, "\t\tOK");
fprintf(stderr, "\nI2C_FUNC_SMBUS_WRITE_BLOCK_DATA ");
if ( I2C_FUNC_SMBUS_WRITE_BLOCK_DATA & funcs) fprintf(stderr, "\tOK");
fprintf(stderr, "\nI2C_FUNC_SMBUS_READ_I2C_BLOCK ");
if ( I2C_FUNC_SMBUS_READ_I2C_BLOCK & funcs) fprintf(stderr, "\t\tOK");
fprintf(stderr, "\nI2C_FUNC_SMBUS_WRITE_I2C_BLOCK ");
if ( I2C_FUNC_SMBUS_WRITE_I2C_BLOCK & funcs) fprintf(stderr, "\t\tOK");
fprintf(stderr, "\n");
memset(ioctlMsg, 0, sizeof(struct i2c_rdwr_ioctl_data) * 2);
ioctlMsg[0].addr = 0x0;
ioctlMsg[0].flags = 0; /* write command */
ioctlMsg[0].len = 1;
ioctlMsg[0].buf = &data;
request.msgs = ioctlMsg;
request.nmsgs = 1;
status = ioctl(file, I2C_RDWR, request);
if(status < 0) {
perror("Write failed");
return 2;
}
close(file);
return 0;
}
I found my problem, turns out that the 'bad address' wasn't referring to the address of the I2C device, but the address of the block being sent in the ioctl command. I had forgotten to pass the address, as opposed to the value of the parameter in my call to ioctl.
Related
using Linux (ubuntu 20.04) machine, openssl 3.0.7 is installed , running a sample code for signing.
we followed below procedure for signing. getting segmentation fault in EVP_DigestFinal_ex.
segmentation fault is happening due to mdctx->algctx=0x0. while debugging the code mdctx->algctx is updated in EVP_DigestInit_ex but latter it was freed in EVP_DigestSignInit. not sure what we are missing and how to update mdctx->algctx to avoid the crash.
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/provider.h>
EVP_PKEY *pkey = NULL;
generate_key(){
EVP_PKEY_CTX *ctx=NULL;
pkey=EVP_PKEY_new();
ctx=EVP_PKEY_CTX_new(pkey,NULL);
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if (!ctx)
printf(" key gen failed");
if (EVP_PKEY_keygen_init(ctx) <= 0)
printf(" key gen failed");
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 512) <= 0)
printf(" key gen failed");
/* Generate key */
if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
printf(" key gen failed");
}
int main(int argc, char *argv[])
{
EVP_MD_CTX *mdctx;
const EVP_MD *m_md;
const EVP_MD *md;
EVP_PKEY *m_key;
EVP_PKEY *ed_pkey = NULL;
EVP_PKEY_CTX *ed_pctx = NULL;
// OSSL_PROVIDER *default;
size_t sign_len = 0;
u_int8_t m_sign_buf[2048];
int ret = 0;
char mess1[] = "Test Message\n";
char mess2[] = "Hello World\n";
unsigned char *outdigest = NULL;
unsigned int md_len = 0, i;
printf("args : %s\n",argv[1]);
//default = OSSL_PROVIDE_load(NULL, "default");
//md = EVP_get_digestbyname("SHA256");
//md = EVP_sha256();
md = EVP_MD_fetch(NULL, "SHA256", NULL); //;
if (md == NULL) {
printf("Unknown message digest %s\n", argv[1]);
exit(1);
}
generate_key();
printf("value of md %s\n",md);
mdctx = EVP_MD_CTX_new();
if((EVP_DigestInit_ex(mdctx, md, NULL)) != 1)
printf("EVP_DigestInit_ex failed \n");
if((EVP_DigestSignInit(mdctx, NULL, md, NULL, pkey)) != 1)
printf("EVP_DigestSignInit failed \n");
if((EVP_DigestSignUpdate(mdctx, mess1, strlen(mess1))) != 1)
printf("EVP_DigestSignUpdate failed \n");
//EVP_DigestUpdate(mdctx, mess2, strlen(mess2));
if((EVP_DigestSignFinal(mdctx, (u_int8_t*)NULL, &sign_len)) != 1)
printf("EVP_DigestSignFinal failed \n");
if((EVP_DigestSignFinal(mdctx, m_sign_buf, &sign_len)) != 1)
printf("EVP_DigestSignFinal 2 failed \n");
/* Allocate the output buffer */
outdigest = OPENSSL_malloc(EVP_MD_get_size(md));
if (outdigest == NULL)
printf("outdigest failed \n");
if((EVP_DigestFinal_ex(mdctx, outdigest, &md_len)) != 1)
printf("EVP_DigestFinal_ex failed \n");
EVP_MD_CTX_free(mdctx);
/* Print out the digest result */
BIO_dump_fp(stdout, outdigest, &md_len);
exit(0);
}
`
```
Thanks,
while debugging the code mdctx->algctx is updated in EVP_DigestInit_ex but latter it was freed in EVP_DigestSignInit. not sure what we are missing and how to update mdctx->algctx to avoid the crash.
CRASH Info:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7d99422 in SHA256_Final (md=0x5555555a88d0 "\250UUU\005", c=0x0)
at ../openssl-3.0.7/include/crypto/md32_common.h:194
194 size_t n = c->num;
(gdb) bt
#0 0x00007ffff7d99422 in SHA256_Final (md=0x5555555a88d0 "\250UUU\005", c=0x0)
at ../openssl-3.0.7/include/crypto/md32_common.h:194
#1 0x00007ffff7e2628c in sha256_internal_final (ctx=0x0, out=0x5555555a88d0 "\250UUU\005", outl=0x7fffffffda98,
outsz=32) at ../openssl-3.0.7/providers/implementations/digests/sha2_prov.c:72
#2 0x00007ffff7cbadf6 in EVP_DigestFinal_ex (ctx=0x555555580d80, md=0x5555555a88d0 "\250UUU\005",
isize=0x7fffffffdad8) at ../openssl-3.0.7/crypto/evp/digest.c:446
#3 0x000055555555575f in main (argc=1, argv=0x7fffffffe458) at test2.c:90
I want to use PJSIP's C API to record the incoming audio to a file on a machine with no hardware sound device .
I'm unsure about the details, but the sparse documentation for PJSIP suggests it should be
possible through the pjsua_set_null_snd_dev() call.
In the fully functioning (Windows biased) example below the call pjmedia_aud_dev_default_param(PJMEDIA_AUD_DEFAULT_CAPTURE_DEV, ¶m) returns PJMEDIA_AUD_INVALID_DEV in the status.
The code generates this same error on Linux (Ubuntu 14) and Windows 10 when there are no hardware audio devices present.
If there is an hardware audio device driver installed the exact same code works fine on both OSes.
I have compiled the PJSIP libraries with PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO enabled.
On Linux the presence of the module snd-dummy does not help.
How do I get access to the audio data stream from a SIP call after calling pjsua_set_null_snd_dev()?
#include <pjlib.h>
#include <pjlib-util.h>
#include <pjnath.h>
#include <pjsip.h>
#include <pjsip_ua.h>
#include <pjsip_simple.h>
#include <pjsua-lib/pjsua.h>
#include <pjmedia.h>
#include <pjmedia-codec.h>
#include <pj/log.h>
#include <pj/os.h>
int main(int, char **)
{
// Create pjsua first!
pj_status_t status = pjsua_create();
if (status != PJ_SUCCESS)
{
fprintf(stderr,"pjsua_create error\n");
return -1;
}
// Init pjsua
pjsua_config cfg;
pjsua_logging_config log_cfg;
pjsua_config_default(&cfg);
pjsua_logging_config_default(&log_cfg);
log_cfg.console_level = 4;
status = pjsua_init(&cfg, &log_cfg, NULL);
if (status != PJ_SUCCESS)
{
fprintf(stderr,"pjsua_init error\n");
return -1;
}
// Proactively list known audio devices so we are sure there are NONE
pjmedia_aud_dev_info info[64];
unsigned info_count = 64;
pjsua_enum_aud_devs(info, &info_count);
fprintf(stderr,"Listing known sound devices, total of [%u]\n", info_count);
for (unsigned i = 0; i<info_count; ++i)
{
fprintf(stderr,"Name [%s]", info[i].name);
}
// Add transport
pjsua_transport_config tcfg;
pjsua_transport_id trans_id;
pjsua_transport_config_default(&tcfg);
tcfg.port = 5060;
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &trans_id);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_transport_create error\n");
return -1;
}
// Initialization is done, now start pjsua
status = pjsua_start();
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_start error\n");
return -1;
}
// Set NULL sound
status = pjsua_set_null_snd_dev();
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_set_null_snd_dev error");
return -1;
}
// Register to a SIP server by creating SIP account, I happen use use Asterisk
pjsua_acc_id acc_id;
fprintf(stderr, "Setting up SIP server registration\n");
{
pjsua_acc_config cfg;
pjsua_acc_config_default(&cfg);
cfg.id = pj_str("sip:6001#10.0.0.21");
cfg.reg_uri = cfg.id; // same as ID
cfg.cred_count = 1;
cfg.cred_info[0].realm = pj_str("*");
cfg.cred_info[0].scheme = pj_str("digest");
cfg.cred_info[0].username = pj_str("6001");
cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
cfg.cred_info[0].data = pj_str("teddy");
status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_acc_add error\n");
return -1;
}
}
fprintf(stderr, "Waiting for SIP server registration to complete....\n");
Sleep(2000); // sleep 2 seconds
// Call extension 9 on my Asterisk server at 10.0.0.21:5060
pj_str_t sip_target(pj_str("sip:9#10.0.0.21"));
fprintf(stderr, "Making call to [%s]\n", sip_target.ptr);
pjsua_call_id call_id;
status = pjsua_call_make_call(acc_id, &sip_target, 0, NULL, NULL, &call_id);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_call_make_call error\n");
return -1;
}
pj_pool_t * pool = nullptr;
pjmedia_port * wav = nullptr;
pjmedia_aud_stream *strm = nullptr;
pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "wav-audio", 1000, 1000, NULL);
if (nullptr == pool)
{
fprintf(stderr,"Pool creation failed\n");
return -1;
}
// 8kHz, single channel 16bit MS WAV format file
status = pjmedia_wav_writer_port_create(pool, "test.wav", 8000, 1, 320, 16, PJMEDIA_FILE_WRITE_PCM, 0, &wav);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "Error creating WAV file\n");
return -1;
}
pjmedia_aud_param param;
//////////////////////////////////////////////////////
// FAILURE HERE : This is the function call which returns PJMEDIA_AUD_INVALID_DEV
//////////////////////////////////////////////////////
status = pjmedia_aud_dev_default_param(PJMEDIA_AUD_DEFAULT_CAPTURE_DEV, ¶m);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjmedia_aud_dev_default_param()");
return -1;
}
param.dir = PJMEDIA_DIR_CAPTURE;
param.clock_rate = PJMEDIA_PIA_SRATE(&wav->info);
param.samples_per_frame = PJMEDIA_PIA_SPF(&wav->info);
param.channel_count = PJMEDIA_PIA_CCNT(&wav->info);
param.bits_per_sample = PJMEDIA_PIA_BITS(&wav->info);
status = pjmedia_aud_stream_create(¶m, &test_rec_cb, &test_play_cb, wav, &strm);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "Error opening the sound stream");
return -1;
}
status = pjmedia_aud_stream_start(strm);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "Error starting the sound device");
return -1;
}
// Spend some time allowing the called party to pick up and recording to proceed
Sleep(10000); // sleep 10 seconds
// Clean up code omitted
return 0;
}
Apologies to the pure of heart for the mix of C and C++ above.
Solved this by loading the Alsa module snd-dummy.
Look in /lib/modules/YOUR_KERNEL_VERSION/modules.dep if its mentioned.
If you have it then load it with modprobe snd-dummy
Otherwise recompile your Kernel to include it as a module or follow the installation in the link above.
I was trying to get CFtpServer's first example program running on a Windows 7 Pro, x64 system. After much beating around the bush and not believing what I was seeing, I got the problem down to the following simple program:
#include <iostream>
using namespace std;
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#define die(code) { cerr << "die at " << __FILE__ << " " << __LINE__ << " "; exit(code); }
int main(int argc, char **argv)
{
short port = 21;
if (argc == 2) {
port = atoi(argv[1]);
}
WSADATA WSAData;
if ( WSAStartup( MAKEWORD(2, 2), &WSAData) != 0)
die(1);
SOCKET ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//!!! proto 0 in ftpdmin!
if (ls == INVALID_SOCKET) die(1);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons( port );
if (bind( ls, (struct sockaddr *) &sin, sizeof( struct sockaddr_in ) )
== SOCKET_ERROR) die(2);
if (listen( ls, 1 ) == SOCKET_ERROR ) //!!! backlog 1 in ftpdmin!
die(3);
// wait for connect, transmit till error
SOCKET ts;
for( ;; ) {
ts = accept( ls, NULL, NULL );
if (ts == INVALID_SOCKET) die(5);
// now write some things to that socket.
int i=0;
for(;;) {
char buf[256];
sprintf(buf, "%d Testing...\r\n",i+224);
if (send(ts, buf, strlen(buf), 0) < 0) {
DWORD err = WSAGetLastError();
cerr << "send failed with " << err << endl;
break;
}
Sleep(1000);
i = (i+1)%10;
}
Sleep(1000);
closesocket(ts);
}
}
This program opens the specified socket, listens on it for connections. When it gets a connection, it proceeds to write strings that bear a passing resemblance to the string an FTP server might use to respond to the PASV command. It will keep transmitting strings, once a second, until something goes wrong.
On my system, connecting to this 'server' using the nc.exe command, I see a few strings, then the socket will close (the error printed by the 'server' is 10053).
If I disabled the Windows firewall, I see strings as long as I care to leave the nc command running.
I've seen two different variations, and I don't know what causes the difference: Sometimes it would stop when it transmitted the string '227 ', later it started dying on '229 '. It's giving every appearance of being sensitive to the text being sent.
After 3 days of beating my head on this one, I have an answer: Window KB2754804. It's a bug, known to MS since somewhere in 2011. There is a Hotfix in the referenced Knowledge base article, but it doesn't seem to work for my tests, so I had to take the alternative route of disabling the Stateful FTP firewall.
I finally got to the KB article, from this SO entry.
I want to implement a simple "cat file1 > file1" command in a C program. I have tried the following, but it does not work...
main () {
pid_t pid;
FILE *ip, *op;
char *args[3];
printf("Name of the executable program\n\t");
scanf("%s", &name[0]); // I entered cat here
printf("Name of the input file\n\t");
scanf("%s", &name[1]); //file1.txt
printf("Name of the output file\n\t");
scanf("%s", &name[0]); //file2.txt
pid = fork();
if(pid == -1)
perror("fork() error");
else if(pid > 0)
waitpid(-1, NULL, 0);
else if (pid == 0) {
op = fopen(name[2], "w");
close(1);
dup(op);
execlp(name[0], name[1], NULL);
}
return 0;
}// end of main()
I thought the execlp() will run cat file1.txt and its output will be redirected to file2.txt, but it's not and I don't know why. How do I do it?
scanf("%s", &name[0]); // I entered cat here
printf("Name of the input file\n\t");
scanf("%s", &name[1]); //file1.txt
printf("Name of the output file\n\t");
scanf("%s", &name[0]); //file2.txt
Clearly not a C&P of actual code - name should be args, and the last one should be "2" instead of 0.
Also, dup works on file descriptors, not FILE*, so need to look at open rather than fopen, or whatever method gets the fd from a FILE*
The first argument to execlp() is the name to be looked up; the second and following arguments are the argv list, starting with argv[0].
int execlp(const char *file, const char *arg0, ... /*, (char *)0 */);
For shell I/O redirection, it is easier to open files with open() than to use standard I/O (<stdio.h> and FILE *); you should also close the file you opened after the dup(), though it is easier to use dup2(). You need to allocate space to read the strings into; on many systems, the original code would crash because the pointers in str don't point anywhere. You should normally aim to exit with status 0 only if everything worked; otherwise, exit with a non-zero exit status.
This leads to:
#include <fcntl.h> /* open() */
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h> /* waitpid() */
#include <unistd.h> /* execlp(), fork(), dup2() */
int main(void)
{
pid_t pid;
pid_t corpse;
int status;
char name[3][50];
printf("Name of the executable program\n\t");
if (scanf("%49s", name[0]) != 1)
return(EXIT_FAILURE);
printf("Name of the input file\n\t");
if (scanf("%49s", name[1]) != 1)
return(EXIT_FAILURE);
printf("Name of the output file\n\t");
if (scanf("%49s", name[2]) != 1)
return(EXIT_FAILURE);
pid = fork();
if (pid == -1)
{
perror("fork() error");
return(EXIT_FAILURE);
}
else if (pid > 0)
corpse = waitpid(-1, &status, 0);
else
{
int fd = open(name[2], O_WRONLY|O_CREAT|O_EXCL, 0644);
if (fd < 0)
{
fprintf(stderr, "Failed to open %s for writing\n", name[2]);
return(EXIT_FAILURE);
}
dup2(fd, 1);
close(fd);
execlp(name[0], name[0], name[1], NULL);
fprintf(stderr, "Failed to exec %s\n", name[0]);
return(EXIT_FAILURE);
}
return(corpse == pid && status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
You have to either use fork() a process and reassign it's file descriptors to previously(manually) open()'ed file, or use system() call to make shell handle it for you.
Can anyone guide me or suggest how to make a client using sockets for live media server streaming over HTTP, as I tried a lot but was not successful.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include<conio.h>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
//************All Declarations**********//
#define DEFAULT_BUFLEN 512000
#define DEFAULT_PORT "8000"
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char *sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Validate the parameters
if (argc != 2) {
printf("usage: %s server-name\n", argv[0]);
getch();
return 1;
}
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
getch();
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
getch();
return 1;
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
getch();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
getch();
return 1;
}
// Send an initial buffer
/*iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
getch();
return 1;
}*/
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
getch();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, DEFAULT_BUFLEN, 0);
if ( iResult > 0 )
printf("Bytes received: %d\n", iResult);
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
// cleanup
getch();
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
I tried the above code, it works well with a server I create. The problem is I am streaming an transport stream file from live media server through http,but when I try to receive the data from my code of client I am able to connect at specific url but could not receive anything.
The easiest solution for you would be to use the openRTSP client from liveMedia as a starting point. It pretty much comes down to implementing the entire RTSP stack as well interleaving the media over the TCP connection. By passing in the "-T " as a command line parameter, you can configure openRTSP to stream over RTSP over TCP. You can then write your own application based on openRTSP in which you can then handle incoming media samples as desired.
I would advise you against implementing this functionality yourself from a socket-level. You would need to implement RTSP, RTP, RTCP, RTSP over HTTP tunneling, SDP, the various RTP payload formats e.g. for H.264. You socket-related code segment above doesn't begin to touch the surface.
If you want to see what the protocol exchange looks like, sniff the traffic from openRTSP to an RTSP server using wireshark. You can also find an RTSP server at liveMedia.
If it's over HTTP you first have to send an HTTP request (and then parse the response). Example.
You don't receive anything because the server is waiting for the request.