Hello,
in my application I need to download (and then process) a file hosted at a given URL (for example: http://www.domain.com/screenshot.jpg).
How to achieve this?
The target is AmigaOS 4.1 Update 1.
It's compiled for OS4 - how more native would you like it? :-) If you meant whether the OS provides a function for downloading files then the answer is no, AFAIK.
And it's a link library, not a shared library or object, so there are no dependencies.
Or you can go very-native-oldshool-way, and write everything from scratch on plain C: handle ip/tcp packets/structures/connects for youself, and download the file as binary data from whatever you need via recv() kind functions. I.e. netinet/in.h, ip.h, maybe tcp.h and co, depends of how deep you want to jump into the roots.
Buld tcp/ip connection like this:
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
cli.sin_family= AF_INET;
cli.sin_addr.s_addr= ip;
cli.sin_port= port;
if(connect(sock,(struct sockaddr *)&cli,
sizeof(cli))<0){
close(sock);
printf("No connect\n");
exit(0);
}
after you connect, recieve the data to buffer via recvfrom() or recv(), and write to local file , then close socket and co. Of course if server to which you will connect are not your one (which after connection just will send data), but plain http, then you will need to deal with http packets as well manually (so RFC on http protocol, to see the bits you need and co). In general all what you will need to do, its just do some http protocol related stuff, and recieve answer (your data).
http protocol are pretty simply (https support will be another deal, because there as far as i remember openssl will be involved), and it can be enough to do something like this:
IMHO it is even more ugly because wget is a simple program you can include in your program's drawer, but the http handler needs installation into the user's system directories.
Why don't you just search Google for a simple httpget example and use this in your code?
FYI, Roadshow does provide a simple handler that you can use, the TCP: device.
You can access online content just like reading/writing a file with a "TCP:[url]/[port]/..."
syntax. I've used it a fair bit in ARexx both for sending/getting data.
For more info, see:
SYS:Documentation/Roadshow/tcp-handler.doc
Then again, I've been told this isn't the best way to do the fastest or most reliable
transfers. For that, you can use kas1e's low level, longhand approach.
@massi
With tcp/ip, "native amiga way" will be the same as any bsd/linux one, just you can use bsdsocket.library (which make no big sense in compare with newlib sockets).
All that downloading of files on lowlevel are discussed a lot by all the hackers for last 20 years everythere , so Thomas's suggestion about getting any gethttp.c from google will almost do all what you need, just some adoptation and understanding will need it.
You can even go deeper if you want real hardcore: once you write a C code for httpget, you can translate that all to the ppc assembler with removing un-necessary parts and optimise it (as most of those hackers do when do shellcodes). For example check x86/linux realisation here. You can see how small is it (and C source is no much bigger), for downloading a file from http and executing it. And as our RoadShow its just almost the same BSD tcp/ip stack, its all will be kind of the same by logic, just different assembler. I.e. will be the same small and lowlevel.
I even found one more example in google which i compile and test on os4 without changes (except that i change ip on os4coding.net's one, and compile it with -D__USE_INLINE__):
I.e. its already works , and get from os4coding http answer. Now you just need to add code for filling correct ip/domen and path to file from whatevewer you need, and save answer to file. Then you can compile it with -S and -O2, and make a real hardcore on asm :)
All those solutions doesn't handle web server response like "moved" or other kind of response.. the best was to use libcurl that can handle everything.. or wget
I'll add my voice to those suggesting using LibCURL. If you were to write something from scratch, you'll effectively end up writing your own version of LibCURL's HTTP handling code. AmigaOS' networking API is the same BSD sockets that all major OSes uses, and LibCurl calls the BSD socket functions directly. So, LibCURL's code is about as "native" as you can get on all of the platforms that it supports.
There is no real reason to write your own from scratch, unless you're doing it for the learning experience.
I agree with you, there is no need to "reinvent the wheel" each time ...
I personally prefer AmigaDOS handlers over other solutions because they are the Amiga way of doing certain things.
Good to list and talk about different techniques anyway.
The TCP handler only opens a simple TCP (telnet) connection. It does not know HTTP or any other protocol. If you want to support chunked transfers, you need to program that. The example only shows a very simple "get that small file from my own server", for example to check for a new version of your software. It's obviously not a complete implementation of all features of the HTTP protocol.
Thanks to all, I now have a working example, it is written in C language and it makes use of the TCP: handler. A bit of refining is needed anyway.
Going forward in my project.
For those interested, I have finalized this topic to a complete application.
The project name is BigSister, available from OS4 Depot, source code included in the package.
And you don't want to use wget ? (ugly method)
@massi
Use libcurl, it's on OS4depot:
http://www.os4depot.net/index.php?function=showfile&file=development/library/misc/libcurl.lha
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
@zzd10h
I prefer a clean solution.
@trixie
Can it be done in a native way, without additional dependencies?
@massi
It's compiled for OS4 - how more native would you like it? :-) If you meant whether the OS provides a function for downloading files then the answer is no, AFAIK.
And it's a link library, not a shared library or object, so there are no dependencies.
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
@massi
Or you can go very-native-oldshool-way, and write everything from scratch on plain C: handle ip/tcp packets/structures/connects for youself, and download the file as binary data from whatever you need via recv() kind functions. I.e. netinet/in.h, ip.h, maybe tcp.h and co, depends of how deep you want to jump into the roots.
Buld tcp/ip connection like this:
after you connect, recieve the data to buffer via recvfrom() or recv(), and write to local file , then close socket and co. Of course if server to which you will connect are not your one (which after connection just will send data), but plain http, then you will need to deal with http packets as well manually (so RFC on http protocol, to see the bits you need and co). In general all what you will need to do, its just do some http protocol related stuff, and recieve answer (your data).
http protocol are pretty simply (https support will be another deal, because there as far as i remember openssl will be involved), and it can be enough to do something like this:
And answer will be your data.
I.e. you make a ip / tcp connection yourself from scratch via ip structs, and deals with http.
@trixie
OK thanks, it can be a way.
@kas1e
I always like the from "scratch" approach :) thanks.
Perhaps it can be achieved through a dedicated AmigaDOS handler / device (HTTP:, ...)?
Anyone aware of this?
Any already existing solutions?
@Massi
There is a http-handler from Chris Young that works pretty well:
http://aminet.net/package/comm/www/httphandler
Why is this less ugly than the wget approach?
IMHO it is even more ugly because wget is a simple program you can include in your program's drawer, but the http handler needs installation into the user's system directories.
Why don't you just search Google for a simple httpget example and use this in your code?
@salass00, @thomas
Thanks.
At this stage I am evaluating possible solutions. Overall I prefer Amiga styled techniques.
@massi
FYI, Roadshow does provide a simple handler that you can use, the TCP: device.
You can access online content just like reading/writing a file with a "TCP:[url]/[port]/..."
syntax. I've used it a fair bit in ARexx both for sending/getting data.
For more info, see:
SYS:Documentation/Roadshow/tcp-handler.doc
Then again, I've been told this isn't the best way to do the fastest or most reliable
transfers. For that, you can use kas1e's low level, longhand approach.
Good luck,
PJS
@massi
With tcp/ip, "native amiga way" will be the same as any bsd/linux one, just you can use bsdsocket.library (which make no big sense in compare with newlib sockets).
All that downloading of files on lowlevel are discussed a lot by all the hackers for last 20 years everythere , so Thomas's suggestion about getting any gethttp.c from google will almost do all what you need, just some adoptation and understanding will need it.
You can even go deeper if you want real hardcore: once you write a C code for httpget, you can translate that all to the ppc assembler with removing un-necessary parts and optimise it (as most of those hackers do when do shellcodes). For example check x86/linux realisation here. You can see how small is it (and C source is no much bigger), for downloading a file from http and executing it. And as our RoadShow its just almost the same BSD tcp/ip stack, its all will be kind of the same by logic, just different assembler. I.e. will be the same small and lowlevel.
I even found one more example in google which i compile and test on os4 without changes (except that i change ip on os4coding.net's one, and compile it with -D__USE_INLINE__):
And there is result:
I.e. its already works , and get from os4coding http answer. Now you just need to add code for filling correct ip/domen and path to file from whatevewer you need, and save answer to file. Then you can compile it with -S and -O2, and make a real hardcore on asm :)
ps. Blah, that source even from amiga.org archives, there is full thread with details, and Piru's example is much better of course
@PJS
Thanks, AmigaDOS handlers (HTTP:, TCP:) are definitely what I was looking for.
@kas1e
Thanks, very valuable contribution and really hacker style which I always appreciate ;)
Here is a Rexx program which downloads a file using the TCP handler:
@thomas
Thanks for this good start, it should be straight to adapt it to C language.
All those solutions doesn't handle web server response like "moved" or other kind of response.. the best was to use libcurl that can handle everything.. or wget
@thomas
Thanks big times ! I got it finally how to use this TCP: device.
@Massi
I'll add my voice to those suggesting using LibCURL. If you were to write something from scratch, you'll effectively end up writing your own version of LibCURL's HTTP handling code. AmigaOS' networking API is the same BSD sockets that all major OSes uses, and LibCurl calls the BSD socket functions directly. So, LibCURL's code is about as "native" as you can get on all of the platforms that it supports.
There is no real reason to write your own from scratch, unless you're doing it for the learning experience.
Hans
Join the Kea Campus - upgrade your skills; support my work; enjoy the Amiga corner.
https://keasigmadelta.com/ - see more of my work
@Hans
I agree with you, there is no need to "reinvent the wheel" each time ...
I personally prefer AmigaDOS handlers over other solutions because they are the Amiga way of doing certain things.
Good to list and talk about different techniques anyway.
@thomas
Isn't it obvious? ;-)
@thomas
Does the Rexx script work with HTTP 1.1 chunked transfer mode (response arriving in multiple parts)?
Perhaps chunked messages are managed within the TCP: handler or?
The TCP handler only opens a simple TCP (telnet) connection. It does not know HTTP or any other protocol. If you want to support chunked transfers, you need to program that. The example only shows a very simple "get that small file from my own server", for example to check for a new version of your software. It's obviously not a complete implementation of all features of the HTTP protocol.
Thanks to all, I now have a working example, it is written in C language and it makes use of the TCP: handler. A bit of refining is needed anyway.
Going forward in my project.
For those interested, I have finalized this topic to a complete application.
The project name is BigSister, available from OS4 Depot, source code included in the package.
Regards