RTMP_Init “Segmentation fault” - c++

I am using librtmp to stream video.I install librtmp in ubuntu 16.04 with "sudo apt-get librtmp-dev".I successfully compiled the code,but I got a "Segmentation fault" in RTMP_Init().Here is my rtmp_test code:
main function:
int main(int argc,char *argv[]){
printf("11111\n");
if (RTMP264_Connect("rtmp://**********") == TRUE){
printf("connect successful");
}
printf("22222222\n");
return 0;
}
RTMP264_Connect function:
int RTMP264_Connect(const char * url){
printf("~~~~~~~1\n");
RTMP_Init(m_Rtmp);
printf("~~~~~~~2\n");
if(RTMP_SetupURL(m_Rtmp,(char*)url) == FALSE){
RTMP_Free(m_Rtmp);
return FALSE;
}
printf("~~~~~~~3\n");
RTMP_EnableWrite(m_Rtmp);
if(RTMP_Connect(m_Rtmp,NULL)==FALSE){
RTMP_Free(m_Rtmp);
return FALSE;
}
When I run the code,I got this error:
11111
aaaa
~~~~~~~1
Segmentation fault
So I'm sure the problem is in RTMP_init function.I saw someone on the Internet saying that the reason may be that socket is not initialized. I found a socket initialization code:
int InitSockets()
{
#ifdef WIN32
WORD version;
WSADATA wsaData;
version = MAKEWORD(1, 1);
return (WSAStartup(version, &wsaData) == 0);
#endif
}
void CleanupSockets()
{
#ifdef WIN32
WSACleanup();
#endif
}
But this is for Windows system. If I run on Ubuntu, I will report an error. And I don't know if my problem has something to do with socket not being initialized.Could someone tell me how to fix my problem,thanks!

According to the documentation:
The basic interaction is as follows. A session handle is created using RTMP_Alloc() and initialized using RTMP_Init().
As you haven't called RTMP_Alloc this is presumably the cause of the segfault

Related

I can't create server application in RakNet ( C++ )

I'm trying create server application in C++ using RakNet.
When i try following code :
#include <stdio.h>
#include "RakPeerInterface.h"
#define MAX_CLIENTS 10
#define SERVER_PORT 60000
int main(void)
{
char str[512];
RakNet::RakPeerInterface *peer = RakNet::RakPeerInterface::GetInstance();
bool isServer;
printf("(C) or (S)erver?\n");
gets(str);
if ((str[0] == 'c') || (str[0] == 'C'))
{
SocketDescriptor sd;
peer->Startup(1, &sd, 1);
isServer = false;
}
else {
SocketDescriptor sd(SERVER_PORT, 0);
peer->Startup(MAX_CLIENTS, &sd, 1);
isServer = true;
}
// TODO - Add code body here
RakNet::RakPeerInterface::DestroyInstance(peer);
return 0;
}
Compiler giving this errors :
I guess i set up RakNet successfully What is missing ?
Well, one that that seems to be missing - if you are using the RakNet SocketDescriptor object is the "RakNet::" part to elt it know which namespace to use?
You have it on the PeerInterface section, but then have not used it on the SocketDescriptor
Also the RakNet socket descriptors are part of the "#include "RakNetTypes.h"" as far as I remember.. which also seems to be missing.. so unless youre using other SocketDescriptors .. that may also be needed :o
Missed the "Gets" part too - there is header for that under "#include "Gets.h"" within Raknet as well

'SDL_main' : must return a value

I am trying to retreive content of websice in c++ usind SDL but it is giving me this error:
'SDL_main' : must return a value
my code is:
#include <iostream>
#include "SDL.h"
#include "SDL_net.h"
#include <cstring>
int main(int argc,char** argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDLNet_Init();
IPaddress ip;
SDLNet_ResolveHost(&ip,"www.linux.org",80);
const char* http="GET / HTTP/1.1\nHost: www.linux.org\n\n";
TCPsocket client=SDLNet_TCP_Open(&ip);
SDLNet_TCP_Send(client,http,strlen(http)+1);
char text[10000];
while(SDLNet_TCP_Recv(client,text,10000))
std::cout << text;
SDLNet_TCP_Close(client);
SDLNet_Quit();
SDL_Quit();
}
When I put return 0; at the end, it built project but it finished immediately after that
(I am using vs2012)
UPDATE
cout<<"Some message";
doesn't print anything, is it possible that I have configured my imports wrong? are those additional dependencies right?
SDL.lib;SDL_net.lib;SDLmain.lib
I don't know what else could be wrong ...
It's because SDL defines a macro like this:
#define main SDL_main
So the function you've written is actually called SDL_main and like any other function that is not the actual main function, if it doesn't return void, you have to give it a return statement.
because your code doesn't loop forever it just returns 0 after first pass, you need to make a loop like:
while(1){
sdl_events event;
switch(event){
//handle events, drawings and so on
...
...
...
case SDL_QUIT:
exit (0);
break;
}
}
http://sdl.beuc.net/sdl.wiki/OpenGL_Full_Example
UPDATE
you may also have some problem connecting to host so you could check if connection succeed like this:
#define MAXLEN 1024
int result;
char msg[MAXLEN];
result = SDLNet_TCP_Recv(sock,msg,MAXLEN-1);
if(result <= 0) {
// TCP Connection is broken. (because of error or closure)
SDLNet_TCP_Close(sock);
exit(1);
}
else {
msg[result] = 0;
printf("Received: \"%s\"\n",msg);
}
UPDATE 2
change this:
while(SDLNet_TCP_Recv(client,text,10000))
std::cout << text;
to this:
while(SDLNet_TCP_Recv(client,text,9999))
std::cout << text;
UPDATE 3
try this, put your receive part in this if statement
if(SDLNet_SocketReady(client) == 1)
{
while(SDLNet_TCP_Recv(client,text,9999))
std::cout << text;
}
if this still doesn't work I suggest to use QT sockets or Boost asio, both async and more intuitive

windows8 - _dup,_dup2

I use win8 Consumer preview build 8250 for executing a program, which works OK on win7
The program uses the following macros/functions:
#if defined(_WIN32)
#include <io.h>
#define streamDup(fd1) _dup(fd1)
#define streamDup2(fd1,fd2) _dup2(fd1,fd2)
#endif
static int acquireOutputStream()
{ int fd = streamDup(fileno(stdout));
FILE* f = freopen("tmp","w",stdout);
return fd; }
static void releaseOutputStream(int fd)
{ fflush(stdout);
streamDup2(fd,fileno(stdout));
close(fd);
}
The program performs the following:
for (int i = 0; i < 1000;++i) {
int fd = acquireOutputStream();
printf("redirect %d\n",i);
releaseOutputStream(fd);
printf("test %d\n",i);
}
Every time I run it ,it prints to file tmp random number of correct "redirect j" printings :
After it ,the file is empty for the remaining executions.(f pointer is never NULL in the acquireOutputStream)"test j" is always printed correctly.
What could be a problem? Is it a known issue on win 8?
There is one small issue i see with your code.
static void releaseOutputStream(int fd)
{ fflush(stdout);
streamDup2(fd,fileno(stdout));
close(fd);
}
In this function you do not close stdout prior to the dup2 call (fclose(stdout)).
Please add more detail to the question on exactly what you are seeing when running this code. It would help in diagnosing the issue.

sending an email from a C/C++ program in linux

I would like to send an email to my gmail account everytime my simulation ends. I have tried searching the web and found sendEmail but it is timing-out. If anyone could point me out to a package or link that they tried I would be thankful.
Thanks
You could invoke your local MTA directly using popen() and feed it RFC822-compliant text.
#include <stdio.h>
#include <string.h>
#include <errno.h>
int sendmail(const char *to, const char *from, const char *subject, const char *message)
{
int retval = -1;
FILE *mailpipe = popen("/usr/lib/sendmail -t", "w");
if (mailpipe != NULL) {
fprintf(mailpipe, "To: %s\n", to);
fprintf(mailpipe, "From: %s\n", from);
fprintf(mailpipe, "Subject: %s\n\n", subject);
fwrite(message, 1, strlen(message), mailpipe);
fwrite(".\n", 1, 2, mailpipe);
pclose(mailpipe);
retval = 0;
}
else {
perror("Failed to invoke sendmail");
}
return retval;
}
main(int argc, char** argv)
{
if (argc == 5) {
sendmail(argv[1], argv[2], argv[3], argv[4]);
}
}
libESMTP seems to be what you are looking for. It's very well documented and also seems to be under active development (last Release Candidate is from mid-January 2012). It also supports SSL and various authentication protocols.
There are example applications in the source package.
Both VMime and libcurl are good libraries for email sending (and more).
I like the answer of trojanfoe above, BUT in my case I needed to turn on an email sending agent.. an MTA to enable linux to send emails - I have found exim4 to be a relatively simple MTA to get working and that trojanfoe's program works very nicely with it.
to get it to work I used (on a debian type system in a virtual box (crunchbang linux))
sudo apt-get install exim
sudo apt-get install mailutils
I configured exim4 with
sudo dpkg-reconfigure exim4-config
and I told the computer about my normal (remote) email address with
sudo emacs /etc/email-addresses
hope this might be useful as these were the steps I found worked to get my linux system sending email with trojanfoe's email program above
Do a fork exec and pipe the body to a program like sendmail/mail:
#include <string>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
using std::string;
static const int READEND = 0;
static const int WRITEEND = 1;
int sendEmail(const string& to, const string& subject, const string& body) {
int p2cFd[2];
int ret = pipe(p2cFd);
if (ret) {
return ret;
}
pid_t child_pid = fork();
if (child_pid < 0) {
close(p2cFd[READEND]);
close(p2cFd[WRITEEND]);
return child_pid;
}
else if (!child_pid) {
dup2(p2cFd[READEND], READEND);
close(p2cFd[READEND]);
close(p2cFd[WRITEEND]);
execlp("mail", "mail", "-s", subject.c_str(), to.c_str(), NULL);
exit(EXIT_FAILURE);
}
close(p2cFd[READEND]);
ret = write(p2cFd[WRITEEND], body.c_str(), body.size());
if (ret < 0) {
return ret;
}
close(p2cFd[WRITEEND]);
if (waitpid(child_pid, &ret, 0) == -1) {
return ret;
}
return 0;
}
int main() {
return sendEmail("email#hostname.com", "Subject", "Body");
}

C++ get linux distribution name\version

According to the question " How to get Linux distribution name and version? ", to get the linux distro name and version, this works:
lsb_release -a
On my system, it shows the needed output:
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 9.10
Release: 9.10
Codename: karmic
Now, to get this info in C++, Qt4's QProcess would be a great option but since I am developing without Qt using std c++, I need to know how to get this info in standard C++, i.e. the stdout of the process, and also a way to parse the info.
Uptil now I am trying to use code from here but am stuck on function read().
You can simply use the function:
int uname(struct utsname *buf);
by including the header
#include <sys/utsname.h>
It already returns the name & version as a part of the structure:
struct utsname
{
char sysname[]; /* Operating system name (e.g., "Linux") */
char nodename[]; /* Name within "some implementation-defined network" */
char release[]; /* OS release (e.g., "2.6.28") */
char version[]; /* OS version */
char machine[]; /* Hardware identifier */
#ifdef _GNU_SOURCE
char domainname[]; /* NIS or YP domain name */
#endif
};
Am I missing something?
For recent linux distros you can use following to get the OS info. The output is pretty standard and can be parsed using following spec:
https://www.freedesktop.org/software/systemd/man/os-release.html
cat /etc/os-release
Sample outputs:
NAME=Fedora
VERSION="27 (Twenty Seven)"
ID=fedora
VERSION_ID=27
PRETTY_NAME="Fedora 27 (Twenty Seven)"
NAME="Ubuntu"
VERSION="16.04.4 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.4 LTS"
VERSION_ID="16.04"
NAME="Arch Linux"
PRETTY_NAME="Arch Linux"
ID=arch
ID_LIKE=archlinux
ANSI_COLOR="0;36"
Got it from cplusplus.com forums, a simple call GetSystemOutput("/usr/bin/lsb_release -a") works.
char* GetSystemOutput(char* cmd){
int buff_size = 32;
char* buff = new char[buff_size];
char* ret = NULL;
string str = "";
int fd[2];
int old_fd[3];
pipe(fd);
old_fd[0] = dup(STDIN_FILENO);
old_fd[1] = dup(STDOUT_FILENO);
old_fd[2] = dup(STDERR_FILENO);
int pid = fork();
switch(pid){
case 0:
close(fd[0]);
close(STDOUT_FILENO);
close(STDERR_FILENO);
dup2(fd[1], STDOUT_FILENO);
dup2(fd[1], STDERR_FILENO);
system(cmd);
//execlp((const char*)cmd, cmd,0);
close (fd[1]);
exit(0);
break;
case -1:
cerr << "GetSystemOutput/fork() error\n" << endl;
exit(1);
default:
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
int rc = 1;
while (rc > 0){
rc = read(fd[0], buff, buff_size);
str.append(buff, rc);
//memset(buff, 0, buff_size);
}
ret = new char [strlen((char*)str.c_str())];
strcpy(ret, (char*)str.c_str());
waitpid(pid, NULL, 0);
close(fd[0]);
}
dup2(STDIN_FILENO, old_fd[0]);
dup2(STDOUT_FILENO, old_fd[1]);
dup2(STDERR_FILENO, old_fd[2]);
return ret;
}
int writepipe[2];
if (pipe(writepipe) < 0) {
perror("pipe");
return 1;
}
int ret = fork();
if (ret < 0) {
perror("fork");
return 1;
}
else if (ret == 0) // child process
{
dup2(writepipe[1],1); // set writepipe[1] as stdout
// close fds
close(writepipe[0]);
close(writepipe[1]);
execlp("lsb_release","lsb_release","-a",NULL); //TODO: Error checking
}
else // parent process
{
int status;
waitpid(ret,&status,0); //TODO: Error checking
//do what you need
//read output of lsb_release from writepipe[0]
}
It works for me
There are files named /etc/version and /etc/release which have information like whether you're using Ubuntu or Fedora, etc. (which is what the OP clarified his question to be).
Personally I like the uname solution posted by #Alok Slav, but in case it helps someone who needs to use a command-line utility to get the info, consider using popen.