Initial import.

This commit is contained in:
Andrew Resch 2007-07-04 08:24:30 +00:00
commit cb4630ded9
362 changed files with 90926 additions and 0 deletions

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.1.5 on Thu Feb 22 19:13:48 2007 by zach@notapowerbook-->
<glade-interface>
<widget class="GtkAboutDialog" id="aboutdialog">
<property name="border_width">5</property>
<property name="destroy_with_parent">True</property>
<property name="skip_taskbar_hint">True</property>
<property name="skip_pager_hint">True</property>
<property name="has_separator">False</property>
<property name="website"></property>
<property name="authors"></property>
<property name="translator-credits"></property>
<property name="documenters"></property>
<property name="artists"></property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="spacing">2</property>
<child>
<placeholder/>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

1140
deluge/glade/delugegtk.glade Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,406 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.2.2 on Wed Jun 20 16:04:00 2007 by andrew@fractal-->
<glade-interface>
<widget class="GtkMenu" id="torrent_popup">
<property name="visible">True</property>
<child>
<widget class="GtkCheckMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="label" translatable="yes">Size</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<signal name="toggled" handler="size_toggle"/>
</widget>
</child>
<child>
<widget class="GtkCheckMenuItem" id="menuitem2">
<property name="visible">True</property>
<property name="label" translatable="yes">Status</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<signal name="toggled" handler="status_toggle"/>
</widget>
</child>
<child>
<widget class="GtkCheckMenuItem" id="menuitem3">
<property name="visible">True</property>
<property name="label" translatable="yes">Seeders</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<signal name="toggled" handler="seeders_toggle"/>
</widget>
</child>
<child>
<widget class="GtkCheckMenuItem" id="menuitem4">
<property name="visible">True</property>
<property name="label" translatable="yes">Peers</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<signal name="toggled" handler="peers_toggle"/>
</widget>
</child>
<child>
<widget class="GtkCheckMenuItem" id="menuitem5">
<property name="visible">True</property>
<property name="label" translatable="yes">Download Speed</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<signal name="toggled" handler="dl_toggle"/>
</widget>
</child>
<child>
<widget class="GtkCheckMenuItem" id="menuitem6">
<property name="visible">True</property>
<property name="label" translatable="yes">Upload Speed</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<signal name="toggled" handler="ul_toggle"/>
</widget>
</child>
<child>
<widget class="GtkCheckMenuItem" id="menuitem7">
<property name="visible">True</property>
<property name="label" translatable="yes">Time Remaining</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<signal name="toggled" handler="eta_toggle"/>
</widget>
</child>
<child>
<widget class="GtkCheckMenuItem" id="menuitem8">
<property name="visible">True</property>
<property name="label" translatable="yes">Share Ratio</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<signal name="toggled" handler="share_toggle"/>
</widget>
</child>
</widget>
<widget class="GtkDialog" id="remove_torrent_dlg">
<property name="title" translatable="yes">Remove Torrent</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="skip_taskbar_hint">True</property>
<property name="skip_pager_hint">True</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox3">
<property name="visible">True</property>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="spacing">10</property>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="spacing">3</property>
<child>
<widget class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-dialog-warning</property>
<property name="icon_size">6</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">5</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;span size="large"&gt;&lt;b&gt;Are you sure you want to remove the selected torrent(s) from Deluge?&lt;/b&gt;&lt;/span&gt;</property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
</widget>
<packing>
<property name="padding">10</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">5</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="left_padding">20</property>
<child>
<widget class="GtkCheckButton" id="data_also">
<property name="visible">True</property>
<property name="label" translatable="yes">Delete downloaded files</property>
<property name="response_id">0</property>
<property name="draw_indicator">True</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="bottom_padding">5</property>
<property name="left_padding">20</property>
<child>
<widget class="GtkCheckButton" id="torrent_also">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Delete .torrent file</property>
<property name="response_id">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="warning">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</widget>
<packing>
<property name="position">3</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">5</property>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area3">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="button2">
<property name="visible">True</property>
<property name="label">gtk-no</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="button1">
<property name="visible">True</property>
<property name="label">gtk-yes</property>
<property name="use_stock">True</property>
<property name="response_id">1</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
</widget>
</child>
</widget>
<widget class="GtkMenu" id="tray_menu">
<property name="visible">True</property>
<child>
<widget class="GtkMenuItem" id="menuitem10">
<property name="visible">True</property>
<property name="label" translatable="yes">Show/Hide</property>
<property name="use_underline">True</property>
<signal name="activate" handler="show_hide_window"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menuitem9">
<property name="visible">True</property>
<property name="label" translatable="yes">Add a Torrent...</property>
<property name="use_underline">True</property>
<signal name="activate" handler="add_torrent"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-add</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menuitem11">
<property name="visible">True</property>
<property name="label" translatable="yes">Clear Finished</property>
<property name="use_underline">True</property>
<signal name="activate" handler="clear_finished"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-clear</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem2">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menuitem12">
<property name="visible">True</property>
<property name="label">gtk-preferences</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<signal name="activate" handler="preferences"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menuitem13">
<property name="visible">True</property>
<property name="label" translatable="yes">Plugins</property>
<property name="use_underline">True</property>
<signal name="activate" handler="plugins"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image3">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-execute</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menuitem14">
<property name="visible">True</property>
<property name="label">gtk-quit</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<signal name="activate" handler="quit"/>
</widget>
</child>
</widget>
<widget class="GtkDialog" id="rate_dialog">
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="border_width">5</property>
<property name="window_position">GTK_WIN_POS_MOUSE</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="skip_taskbar_hint">True</property>
<property name="decorated">False</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="spacing">2</property>
<child>
<widget class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="spacing">10</property>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Rate:</property>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkSpinButton" id="spin_rate">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_focus">True</property>
<property name="is_focus">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="activates_default">True</property>
<property name="xalign">1</property>
<property name="adjustment">0 -1 10000 1 10 10</property>
<property name="numeric">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="button3">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="button4">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label">gtk-ok</property>
<property name="use_stock">True</property>
<property name="response_id">1</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.2.2 on Wed Jun 27 17:27:11 2007 by markybob@peg-->
<glade-interface>
<widget class="GtkWindow" id="edittrackers">
<property name="width_request">300</property>
<property name="height_request">200</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="title" translatable="yes">Edit Trackers</property>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkLabel" id="label1">
<property name="height_request">36</property>
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Tracker Editing</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<child>
<widget class="GtkTextView" id="txt_tracker_list">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</widget>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkAspectFrame" id="aspectframe1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label_xalign">0</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<property name="ratio">1</property>
<child>
<placeholder/>
</child>
</widget>
</child>
<child>
<widget class="GtkButton" id="cancel_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
<signal name="clicked" handler="cancel_button_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="ok_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">gtk-ok</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
<signal name="clicked" handler="ok_button_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkAspectFrame" id="aspectframe2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label_xalign">0</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<property name="ratio">1</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="position">3</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View file

@ -0,0 +1,100 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkMenu" id="file_tab_menu">
<property name="visible">True</property>
<child>
<widget class="GtkImageMenuItem" id="select_all">
<property name="visible">True</property>
<property name="label" translatable="yes">Select All</property>
<property name="use_underline">True</property>
<signal name="activate" handler="select_all" last_modification_time="Mon, 11 Jun 2007 12:54:52 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image22">
<property name="visible">True</property>
<property name="stock">gtk-select-all</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="unselect_all">
<property name="visible">True</property>
<property name="label" translatable="yes">Unselect All</property>
<property name="use_underline">True</property>
<signal name="activate" handler="unselect_all" last_modification_time="Mon, 11 Jun 2007 13:16:59 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image23">
<property name="visible">True</property>
<property name="stock">gtk-file</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separator">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="check_selected">
<property name="visible">True</property>
<property name="label" translatable="yes">Check Selected</property>
<property name="use_underline">True</property>
<signal name="activate" handler="check_selected" last_modification_time="Mon, 11 Jun 2007 12:54:52 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image24">
<property name="visible">True</property>
<property name="stock">gtk-ok</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="uncheck_selected">
<property name="visible">True</property>
<property name="label" translatable="yes">Uncheck Selected</property>
<property name="use_underline">True</property>
<signal name="activate" handler="uncheck_selected" last_modification_time="Mon, 11 Jun 2007 12:54:52 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image25">
<property name="visible">True</property>
<property name="stock">gtk-remove</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
</widget>
</glade-interface>

View file

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--*- mode: xml -*-->
<glade-interface>
<widget class="GtkDialog" id="plugin_dialog">
<property name="width_request">480</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Plugin Manager</property>
<property name="default_width">583</property>
<property name="default_height">431</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="skip_taskbar_hint">True</property>
<property name="skip_pager_hint">True</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK</property>
<property name="spacing">2</property>
<child>
<widget class="GtkNotebook" id="pref_notebook1">
<property name="visible">True</property>
<property name="show_tabs">False</property>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<child>
<widget class="GtkTreeView" id="plugin_view">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<child>
<widget class="GtkTextView" id="plugin_text">
<property name="visible">True</property>
<property name="editable">False</property>
<property name="wrap_mode">GTK_WRAP_WORD</property>
<property name="cursor_visible">False</property>
</widget>
<packing>
<property name="padding">10</property>
</packing>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox2">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
<child>
<widget class="GtkButton" id="plugin_conf">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="label">gtk-preferences</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="plugin_pref"/>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">10</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="tab_expand">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label34">
<property name="visible">True</property>
<property name="label" translatable="yes">Plugins</property>
</widget>
<packing>
<property name="type">tab</property>
<property name="tab_expand">False</property>
<property name="tab_fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="button10">
<property name="visible">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,165 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--*- mode: xml -*-->
<glade-interface>
<widget class="GtkMenu" id="torrent_menu">
<property name="visible">True</property>
<child>
<widget class="GtkImageMenuItem" id="menu_pause">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label">gtk-media-pause</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<signal name="activate" handler="start_pause"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menuitem5">
<property name="visible">True</property>
<property name="label" translatable="yes">_Update Tracker</property>
<property name="use_underline">True</property>
<signal name="activate" handler="update_tracker"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image5">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-refresh</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menuitem13">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_Edit Trackers</property>
<property name="use_underline">True</property>
<signal name="activate" handler="edit_trackers"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image12">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-edit</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separator">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menuitem12">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_Remove Torrent</property>
<property name="use_underline">True</property>
<signal name="activate" handler="remove_torrent"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image9">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-remove</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separator">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menuitem2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_Queue</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menu1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkImageMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_Top</property>
<property name="use_underline">True</property>
<signal name="activate" handler="queue_top"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image10">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-goto-top</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menuitem6">
<property name="visible">True</property>
<property name="label" translatable="yes">_Up</property>
<property name="use_underline">True</property>
<signal name="activate" handler="queue_up"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image6">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-go-up</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menuitem7">
<property name="visible">True</property>
<property name="label" translatable="yes">_Down</property>
<property name="use_underline">True</property>
<signal name="activate" handler="queue_down"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image7">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-go-down</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menuitem8">
<property name="visible">True</property>
<property name="label" translatable="yes">_Bottom</property>
<property name="use_underline">True</property>
<signal name="activate" handler="queue_bottom"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image8">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-goto-bottom</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image11">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-sort-ascending</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
</widget>
</glade-interface>

View file

@ -0,0 +1,158 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--*- mode: xml -*-->
<glade-interface>
<widget class="GtkMenu" id="tray_menu">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkCheckMenuItem" id="show_hide_window">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_Show Deluge</property>
<property name="use_underline">True</property>
<signal name="activate" handler="show_hide_window_toggled"/>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="add_torrent">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_Add Torrent</property>
<property name="use_underline">True</property>
<signal name="activate" handler="add_torrent"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-add</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="clear_finished">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_Clear Finished</property>
<property name="use_underline">True</property>
<signal name="activate" handler="clear_finished"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-clear</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem3">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="download_limit">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_Download Limit</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menu1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</widget>
</child>
<child internal-child="image">
<widget class="GtkImage" id="download-limit-image">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-missing-image</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="upload_limit">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_Upload Limit</property>
<property name="use_underline">True</property>
<child internal-child="image">
<widget class="GtkImage" id="upload-limit-image">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-missing-image</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem4">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="preferences">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label">gtk-preferences</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<signal name="activate" handler="preferences"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="plugins">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Plu_gins</property>
<property name="use_underline">True</property>
<signal name="activate" handler="plugins"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image3">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-disconnect</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="quit">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_Quit</property>
<property name="use_underline">True</property>
<signal name="activate" handler="quit"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image4">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-quit</property>
<property name="icon_size">1</property>
</widget>
</child>
</widget>
</child>
</widget>
</glade-interface>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
deluge/pixmaps/deluge22.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
deluge/pixmaps/deluge32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

View file

@ -0,0 +1,13 @@
[Desktop Entry]
Version=1.0
Encoding=UTF-8
Name=Deluge BitTorrent Client
Comment=Bittorrent client written in PyGTK
Exec=deluge
Icon=deluge.xpm
Terminal=false
Type=Application
Categories=Application;Network
StartupNotify=true
MimeType=application/x-bittorrent;
GenericName=

View file

@ -0,0 +1,415 @@
/* XPM */
static char * deluge_torrent_xpm[] = {
"32 32 380 2",
" c None",
". c #8893A8",
"+ c #8994A8",
"@ c #B0B7C5",
"# c #919BAE",
"$ c #737F98",
"% c #A3ABBB",
"& c #8E98AD",
"* c #AEB5C4",
"= c #858FA5",
"- c #5E6D89",
"; c #929CB0",
"> c #8794A9",
", c #8592AA",
"' c #919FB5",
") c #A5B0C3",
"! c #7688A4",
"~ c #7687A1",
"{ c #8A99B1",
"] c #768AA7",
"^ c #7E92AE",
"/ c #8397B3",
"( c #92A4BD",
"_ c #96A8C0",
": c #5B7295",
"< c #8B9DB7",
"[ c #6A83A4",
"} c #728BAD",
"| c #7791B3",
"1 c #7B95B6",
"2 c #7C96B8",
"3 c #95ABC6",
"4 c #829CBC",
"5 c #45618C",
"6 c #7F96B3",
"7 c #6483A9",
"8 c #6384AC",
"9 c #6B8BB3",
"0 c #7091B8",
"a c #7495BC",
"b c #7596BD",
"c c #7496BD",
"d c #95AECC",
"e c #6F91B9",
"f c #6081A9",
"g c #3C6292",
"h c #365989",
"i c #4B6B97",
"j c #5676A1",
"k c #5F81AB",
"l c #6E93BF",
"m c #7097C2",
"n c #7297C3",
"o c #8FADCE",
"p c #618AB7",
"q c #476D9D",
"r c #5A779F",
"s c #1B4075",
"t c #1F4377",
"u c #365785",
"v c #4A6791",
"w c #4D6B94",
"x c #5D80AA",
"y c #6C93BF",
"z c #779DC6",
"A c #84A6CB",
"B c #5382B6",
"C c #3A659A",
"D c #5C789F",
"E c #224579",
"F c #1E4277",
"G c #274A7C",
"H c #2E4F7F",
"I c #335483",
"J c #44628D",
"K c #557197",
"L c #526E95",
"M c #506F99",
"N c #668FBD",
"O c #7FA3CA",
"P c #7299C4",
"Q c #36639A",
"R c #4F6D97",
"S c #345484",
"T c #305181",
"U c #42618A",
"V c #4E6992",
"W c #4A678F",
"X c #4B6992",
"Y c #4B6994",
"Z c #5F7A9E",
"` c #5E779C",
" . c #597398",
".. c #527099",
"+. c #618ABA",
"@. c #84A6CD",
"#. c #5D89BB",
"$. c #375A89",
"%. c #4C6992",
"&. c #3A5986",
"*. c #536E94",
"=. c #577197",
"-. c #6F92BB",
";. c #759ECA",
">. c #739CCA",
",. c #759DC9",
"'. c #6880A4",
"). c #5C7699",
"!. c #4F6F98",
"~. c #618DBD",
"{. c #81A4CA",
"]. c #4B7CB3",
"^. c #274F84",
"/. c #5A759B",
"(. c #375784",
"_. c #577196",
":. c #5A7498",
"<. c #6F89AB",
"[. c #8BADD1",
"}. c #7EA5D0",
"|. c #7FA6D0",
"1. c #7CA4CF",
"2. c #7CA4CE",
"3. c #789FC7",
"4. c #6984A7",
"5. c #5A7398",
"6. c #5076A5",
"7. c #6791C0",
"8. c #7198C3",
"9. c #2D5081",
"0. c #25477A",
"a. c #4C6890",
"b. c #627A9D",
"c. c #657DA1",
"d. c #A0BBD7",
"e. c #89AED6",
"f. c #8BAFD7",
"g. c #8BB0D7",
"h. c #8AAED6",
"i. c #86ACD4",
"j. c #82A8D2",
"k. c #7CA3CF",
"l. c #749DC8",
"m. c #6984A6",
"n. c #567298",
"o. c #5786BA",
"p. c #779CC6",
"q. c #5583B7",
"r. c #295086",
"s. c #2C4E7F",
"t. c #345483",
"u. c #5B7498",
"v. c #5D7699",
"w. c #93AAC4",
"x. c #9EBDDD",
"y. c #96B8DD",
"z. c #97B9DE",
"A. c #94B7DC",
"B. c #90B3DA",
"C. c #8AAFD6",
"D. c #83A9D2",
"E. c #7AA2CE",
"F. c #6F95BF",
"G. c #667E9F",
"H. c #577FAF",
"I. c #5585B8",
"J. c #759AC5",
"K. c #3F6FA7",
"L. c #254A80",
"M. c #5C769C",
"N. c #3C5B87",
"O. c #60789C",
"P. c #B0C3D8",
"Q. c #A1C0E3",
"R. c #A3C2E4",
"S. c #A3C3E5",
"T. c #A2C2E4",
"U. c #9EBFE2",
"V. c #98BADE",
"W. c #91B4DA",
"X. c #88AED6",
"Y. c #759ECB",
"Z. c #6885AD",
"`. c #5780B0",
" + c #5383B8",
".+ c #7299C3",
"++ c #4675AB",
"@+ c #395A89",
"#+ c #46648F",
"$+ c #3E5D88",
"%+ c #617A9C",
"&+ c #637B9D",
"*+ c #BFD1E4",
"=+ c #ADCBEA",
"-+ c #B0CDEB",
";+ c #AFCCEB",
">+ c #ACCAE9",
",+ c #A7C6E6",
"'+ c #9FC0E2",
")+ c #8DB1D8",
"!+ c #82A9D2",
"~+ c #77A0CC",
"{+ c #6A94C4",
"]+ c #5F8DBF",
"^+ c #5C89BA",
"/+ c #5C85B4",
"(+ c #3F5E8B",
"_+ c #3B5A86",
":+ c #647C9E",
"<+ c #61799D",
"[+ c #C1D2E4",
"}+ c #BBD5F1",
"|+ c #BCD6F2",
"1+ c #BAD5F1",
"2+ c #B5D1EE",
"3+ c #AECBEA",
"4+ c #A5C4E5",
"5+ c #9BBCE0",
"6+ c #84AAD3",
"7+ c #78A0CC",
"8+ c #6B96C6",
"9+ c #5F8CBF",
"0+ c #5282B8",
"a+ c #4F7FB4",
"b+ c #668CB7",
"c+ c #43618D",
"d+ c #325382",
"e+ c #5E779B",
"f+ c #5F789A",
"g+ c #BACADC",
"h+ c #C9E0F9",
"i+ c #C7DFF8",
"j+ c #C3DCF6",
"k+ c #BCD7F2",
"l+ c #B3CFED",
"m+ c #A8C7E7",
"n+ c #9DBEE1",
"o+ c #6A96C5",
"p+ c #5D8BBE",
"q+ c #5081B7",
"r+ c #497BB2",
"s+ c #698DB7",
"t+ c #45638E",
"u+ c #2E5080",
"v+ c #25487B",
"w+ c #506B93",
"x+ c #647B9E",
"y+ c #9DAFC7",
"z+ c #D6E9FD",
"A+ c #D1E8FE",
"B+ c #CAE2FA",
"C+ c #C1DAF5",
"D+ c #A9C8E8",
"E+ c #6894C4",
"F+ c #5A89BC",
"G+ c #4D7EB5",
"H+ c #4577AF",
"I+ c #6B8DB5",
"J+ c #3B6090",
"K+ c #3D5D8A",
"L+ c #3C5B89",
"M+ c #1D4276",
"N+ c #647C9C",
"O+ c #657D9E",
"P+ c #C2D4E6",
"Q+ c #D3E9FF",
"R+ c #CEE5FC",
"S+ c #C2DBF5",
"T+ c #80A7D1",
"U+ c #729CC9",
"V+ c #6491C2",
"W+ c #5686BA",
"X+ c #497BB3",
"Y+ c #5580B3",
"Z+ c #5B7EAA",
"`+ c #335686",
" @ c #4D6993",
".@ c #26497B",
"+@ c #4C6990",
"@@ c #6B82A2",
"#@ c #7D92B0",
"$@ c #C1D4E9",
"%@ c #C0DAF4",
"&@ c #B2CFED",
"*@ c #7BA3CE",
"=@ c #6F99C7",
"-@ c #6390C0",
";@ c #5886B9",
">@ c #4A7BB2",
",@ c #698CB7",
"'@ c #4C6F9C",
")@ c #284C7F",
"!@ c #577299",
"~@ c #2F517F",
"{@ c #536E93",
"]@ c #7086A5",
"^@ c #7B8FAC",
"/@ c #9FB3CD",
"(@ c #B8D2EE",
"_@ c #91B5DB",
":@ c #85ABD4",
"<@ c #7CA3CD",
"[@ c #729AC8",
"}@ c #6791C1",
"|@ c #5A87BA",
"1@ c #5280B4",
"2@ c #7A97BB",
"3@ c #416290",
"4@ c #2F5080",
"5@ c #4F6B91",
"6@ c #687F9F",
"7@ c #7B8FAB",
"8@ c #8396B0",
"9@ c #8AA1BF",
"0@ c #8CACCE",
"a@ c #8FB2D8",
"b@ c #86AAD2",
"c@ c #7DA3CC",
"d@ c #749BC7",
"e@ c #6993C1",
"f@ c #5B88B9",
"g@ c #7999C0",
"h@ c #587AA5",
"i@ c #21416E",
"j@ c #516D96",
"k@ c #415F8A",
"l@ c #567196",
"m@ c #637B9E",
"n@ c #6F84A3",
"o@ c #778BA7",
"p@ c #758BAA",
"q@ c #7490B3",
"r@ c #749BC5",
"s@ c #6992C0",
"t@ c #799DC4",
"u@ c #7291B6",
"v@ c #46658C",
"w@ c #264878",
"x@ c #4F6C94",
"y@ c #42608C",
"z@ c #294B7D",
"A@ c #4A6790",
"B@ c #567095",
"C@ c #597599",
"D@ c #587398",
"E@ c #536F96",
"F@ c #4F6D95",
"G@ c #7690B4",
"H@ c #7090B7",
"I@ c #4A6991",
"J@ c #2B4871",
"K@ c #41608C",
"L@ c #59749A",
"M@ c #234679",
"N@ c #214578",
"O@ c #3A5A87",
"P@ c #47648F",
"Q@ c #667EA2",
"R@ c #7188A9",
"S@ c #4B6892",
"T@ c #395985",
"U@ c #1C314F",
"V@ c #2E4F7D",
"W@ c #395986",
"X@ c #526E96",
"Y@ c #58739A",
"Z@ c #5B759B",
"`@ c #6A82A5",
" # c #627CA0",
".# c #365887",
"+# c #324B69",
"@# c #344B69",
"## c #34537D",
"$# c #294C7C",
"%# c #315383",
"&# c #40618D",
"*# c #40638F",
"=# c #3B5C87",
"-# c #36537A",
";# c #2E4156",
" ",
" . ",
" + @ # ",
" $ % & * = ",
" - ; > , ' ) ! ",
" ~ { ] ^ / ( _ ",
" : < [ } | 1 2 3 4 ",
" 5 6 7 8 9 0 a b c d e ",
" 7 f g h i j k l m n o p ",
" q r s s s t u v w x y z A B ",
" C D E s F G H I J K L M N O P ",
" Q R S s T U V W X Y Z ` ...+.@.#. ",
" $.%.t &.*.=.r -.;.>.,.0 '.).!.~.{.]. ",
" ^./.F (._.:.<.[.}.|.}.1.2.3.4.5.6.7.8. ",
" 9.v 0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q. ",
" r.v s.t.u.v.w.x.y.z.z.A.B.C.D.E.F.G.H.I.J.K. ",
" L.M.s N.b.O.P.Q.R.S.T.U.V.W.X.|.Y.Z.`. +.+++ ",
" @+#+s $+%+&+*+=+-+;+>+,+'+z.)+!+~+{+]+ +^+/+ ",
" (+S s _+:+<+[+}+|+1+2+3+4+5+B.6+7+8+9+0+a+b+ ",
" c+T s d+e+f+g+h+i+j+k+l+m+n+W.6+~+o+p+q+r+s+ ",
" t+u+s v+w+x+y+z+A+B+C+2+D+n+B.D.Y.E+F+G+H+I+J+ ",
" K+L+s M+N.N+O+P+Q+R+S+2+m+5+)+T+U+V+W+X+Y+Z+ ",
" `+ @s s .@+@@@#@$@R+%@&@4+z.e.*@=@-@;@>@,@'@ ",
" )@!@t s s ~@{@]@^@/@(@=+'+_@:@<@[@}@|@1@2@3@ ",
" S #+s s s 4@5@6@7@8@9@0@a@b@c@d@e@f@g@h@ ",
" i@j@u s s s G k@l@m@n@o@p@q@a r@s@t@u@v@ ",
" w@x@y@s s s s z@_+A@B@C@D@E@F@G@H@I@ ",
" J@K@L@y@M@s s N@z@S O@P@Q@R@S@T@ ",
" U@V@W@X@L@Y@Z@L@c.`@ #v .#+# ",
" @###$#%#&#*#=#-#;# ",
" ",
" "};

0
deluge/src/__init__.py Normal file
View file

43
deluge/src/core.py Normal file
View file

@ -0,0 +1,43 @@
#
# core.py
#
# Copyright (C) Andrew Resch 2007 <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
# Instantiate the logger
import logging
log = logging.getLogger("deluge")
class Core:
def __init__(self):
log.debug("Core init..")
def test(self):
print "test"

61
deluge/src/daemon.py Normal file
View file

@ -0,0 +1,61 @@
#
# daemon.py
#
# Copyright (C) Andrew Resch 2007 <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
# Instantiate the logger
import logging
log = logging.getLogger("deluge")
import Pyro.core
from deluge.core import Core
class Daemon:
def __init__(self):
# Instantiate the Manager class
self.core = Core()
# Initialize the Pyro core and daemon
Pyro.core.initServer(banner=0)
log.info("Pyro server initiliazed..")
self.daemon = Pyro.core.Daemon()
# Connect the Manager to the Pyro server
obj = Pyro.core.ObjBase()
obj.delegateTo(self.core)
self.uri = self.daemon.connect(obj, "core")
log.debug("uri: %s", self.uri)
def start(self):
# Start the main loop for the pyro daemon
self.daemon.requestLoop()
def getURI(self):
# Return the URI for the Pyro server
return self.uri

99
deluge/src/main.py Normal file
View file

@ -0,0 +1,99 @@
#!/usr/bin/env python
#
# main.py
#
# Copyright (C) Zach Tibbitts 2006 <zach@collegegeek.org>
# Copyright (C) Alon Zakai 2006 <kripkensteiner@gmail.com>
# Copyright (C) Andrew Resch 2007 <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
# The main starting point for the program. This function is called when the
# user runs the command 'deluge'.
import os
import signal
from optparse import OptionParser
import deluge.common
from deluge.daemon import Daemon
from deluge.ui import Ui
# Setup the logger
import logging
logging.basicConfig(
level=logging.DEBUG,
format="[%(levelname)-8s] %(name)s:%(module)s:%(lineno)d %(message)s"
)
# Get the logger for deluge
log = logging.getLogger("deluge")
def main():
log.info("Starting Deluge..")
# Setup the argument parser
parser = OptionParser(usage="%prog [options] [actions]", version=deluge.common.PROGRAM_VERSION)
parser.add_option("--daemon", dest="daemon", help="Start Deluge daemon",
metavar="DAEMON", action="store_true", default=False)
parser.add_option("--ui", dest="ui", help="Start Deluge UI",
metavar="UI", action="store_true", default=False)
# Get the options and args from the OptionParser
(options, args) = parser.parse_args()
log.debug("options: %s", options)
log.debug("args: %s", args)
daemon = None
pid = None
uri = None
# Start the daemon
if options.daemon:
log.info("Starting daemon..")
daemon = Daemon()
uri = daemon.getURI()
# We need to fork() the process to run it in the background...
pid = os.fork()
if not pid:
daemon.start()
# Start the UI
if options.ui:
log.info("Starting ui..")
ui = Ui(uri)
# Stop Deluge
log.info ("Stopping Deluge..")
# Kill the daemon
if pid:
log.info("Killing daemon..")
os.kill(pid, signal.SIGTERM)

48
deluge/src/ui.py Normal file
View file

@ -0,0 +1,48 @@
#
# ui.py
#
# Copyright (C) Andrew Resch 2007 <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
# Instantiate the logger
import logging
log = logging.getLogger("deluge")
import Pyro.core
class Ui:
def __init__(self, core_uri):
log.debug("Ui init..")
log.debug("core_uri: %s", core_uri)
# Get the core manager from the Pyro server
self.core = Pyro.core.getProxyForURI(core_uri)
# Test
self.core.test()

231
ez_setup.py Normal file
View file

@ -0,0 +1,231 @@
#!python
"""Bootstrap setuptools installation
If you want to use setuptools in your package's setup.py, just include this
file in the same directory with it, and add this to the top of your setup.py::
from ez_setup import use_setuptools
use_setuptools()
If you want to require a specific version of setuptools, set a download
mirror, or use an alternate download directory, you can do so by supplying
the appropriate options to ``use_setuptools()``.
This file can also be run as a script to install or upgrade setuptools.
"""
import sys
DEFAULT_VERSION = "0.6c6"
DEFAULT_URL = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3]
md5_data = {
'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
}
import sys, os
def _validate_md5(egg_name, data):
if egg_name in md5_data:
from md5 import md5
digest = md5(data).hexdigest()
if digest != md5_data[egg_name]:
print >>sys.stderr, (
"md5 validation of %s failed! (Possible download problem?)"
% egg_name
)
sys.exit(2)
return data
def use_setuptools(
version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
download_delay=15
):
"""Automatically find/download setuptools and make it available on sys.path
`version` should be a valid setuptools version number that is available
as an egg for download under the `download_base` URL (which should end with
a '/'). `to_dir` is the directory where setuptools will be downloaded, if
it is not already available. If `download_delay` is specified, it should
be the number of seconds that will be paused before initiating a download,
should one be required. If an older version of setuptools is installed,
this routine will print a message to ``sys.stderr`` and raise SystemExit in
an attempt to abort the calling script.
"""
try:
import setuptools
if setuptools.__version__ == '0.0.1':
print >>sys.stderr, (
"You have an obsolete version of setuptools installed. Please\n"
"remove it from your system entirely before rerunning this script."
)
sys.exit(2)
except ImportError:
egg = download_setuptools(version, download_base, to_dir, download_delay)
sys.path.insert(0, egg)
import setuptools; setuptools.bootstrap_install_from = egg
import pkg_resources
try:
pkg_resources.require("setuptools>="+version)
except pkg_resources.VersionConflict, e:
# XXX could we install in a subprocess here?
print >>sys.stderr, (
"The required version of setuptools (>=%s) is not available, and\n"
"can't be installed while this script is running. Please install\n"
" a more recent version first.\n\n(Currently using %r)"
) % (version, e.args[0])
sys.exit(2)
def download_setuptools(
version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
delay = 15
):
"""Download setuptools from a specified location and return its filename
`version` should be a valid setuptools version number that is available
as an egg for download under the `download_base` URL (which should end
with a '/'). `to_dir` is the directory where the egg will be downloaded.
`delay` is the number of seconds to pause before an actual download attempt.
"""
import urllib2, shutil
egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
url = download_base + egg_name
saveto = os.path.join(to_dir, egg_name)
src = dst = None
if not os.path.exists(saveto): # Avoid repeated downloads
try:
from distutils import log
if delay:
log.warn("""
---------------------------------------------------------------------------
This script requires setuptools version %s to run (even to display
help). I will attempt to download it for you (from
%s), but
you may need to enable firewall access for this script first.
I will start the download in %d seconds.
(Note: if this machine does not have network access, please obtain the file
%s
and place it in this directory before rerunning this script.)
---------------------------------------------------------------------------""",
version, download_base, delay, url
); from time import sleep; sleep(delay)
log.warn("Downloading %s", url)
src = urllib2.urlopen(url)
# Read/write all in one block, so we don't create a corrupt file
# if the download is interrupted.
data = _validate_md5(egg_name, src.read())
dst = open(saveto,"wb"); dst.write(data)
finally:
if src: src.close()
if dst: dst.close()
return os.path.realpath(saveto)
def main(argv, version=DEFAULT_VERSION):
"""Install or upgrade setuptools and EasyInstall"""
try:
import setuptools
except ImportError:
egg = None
try:
egg = download_setuptools(version, delay=0)
sys.path.insert(0,egg)
from setuptools.command.easy_install import main
return main(list(argv)+[egg]) # we're done here
finally:
if egg and os.path.exists(egg):
os.unlink(egg)
else:
if setuptools.__version__ == '0.0.1':
# tell the user to uninstall obsolete version
use_setuptools(version)
req = "setuptools>="+version
import pkg_resources
try:
pkg_resources.require(req)
except pkg_resources.VersionConflict:
try:
from setuptools.command.easy_install import main
except ImportError:
from easy_install import main
main(list(argv)+[download_setuptools(delay=0)])
sys.exit(0) # try to force an exit
else:
if argv:
from setuptools.command.easy_install import main
main(argv)
else:
print "Setuptools version",version,"or greater has been installed."
print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
def update_md5(filenames):
"""Update our built-in md5 registry"""
import re
from md5 import md5
for name in filenames:
base = os.path.basename(name)
f = open(name,'rb')
md5_data[base] = md5(f.read()).hexdigest()
f.close()
data = [" %r: %r,\n" % it for it in md5_data.items()]
data.sort()
repl = "".join(data)
import inspect
srcfile = inspect.getsourcefile(sys.modules[__name__])
f = open(srcfile, 'rb'); src = f.read(); f.close()
match = re.search("\nmd5_data = {\n([^}]+)}", src)
if not match:
print >>sys.stderr, "Internal error!"
sys.exit(2)
src = src[:match.start(1)] + repl + src[match.end(1):]
f = open(srcfile,'w')
f.write(src)
f.close()
if __name__=='__main__':
if len(sys.argv)>2 and sys.argv[1]=='--md5update':
update_md5(sys.argv[2:])
else:
main(sys.argv[1:])

25
libtorrent/AUTHORS Normal file
View file

@ -0,0 +1,25 @@
Written by Arvid Norberg. Copyright (c) 2003-2007
Lots of testing, suggestions and contributions by:
Massaroddel
Tianhao Qiu.
Contributions by:
Shyam
Magnus Jonsson
Daniel Wallin
Cory Nelson
Stas Khirman
Ryan Norton
Building and maintainance of the autotools scripts:
Michael Wojciechowski
Peter Koeleman
Thanks to Reimond Retz for bugfixes, suggestions and testing
Thanks to University of UmeŒ for providing development and test hardware.
Project is hosted by sourceforge.

28
libtorrent/COPYING Normal file
View file

@ -0,0 +1,28 @@
Copyright (c) 2003 - 2007, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of Rasterbar Software nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

216
libtorrent/ChangeLog Normal file
View file

@ -0,0 +1,216 @@
* Fixed bug in URL parser that failed to parse IPv6 addresses
* added peer download rate approximation
* added port filter for outgoing connection (to prevent
triggering firewalls)
* made most parameters configurable via session_settings
* added encryption support
* added parole mode for peers whose data fails the hash check.
* optimized heap usage in piece-picker and web seed downloader.
* fixed bug in DHT where older write tokens weren't accepted.
* added support for sparse files.
* introduced speed categories for peers and pieces, to separate
slow and fast peers.
* added a half-open tcp connection limit that takes all connections
in to account, not just peer connections.
* added alerts for filtered IPs.
* added support for SOCKS4 and 5 proxies and HTTP CONNECT proxies.
* fixed proper distributed copies calculation.
* added option to use openssl for sha-1 calculations.
* optimized the piece picker in the case where a peer is a seed.
* added support for local peer discovery
* removed the dependency on the compiled boost.date_time library
* deprecated torrent_info::print()
* added UPnP support
* fixed problem where peer interested flags were not updated correctly
when pieces were filtered
* improvements to ut_pex messages, including support for seed flag
* prioritizes upload bandwidth to peers that might send back data
* the following functions have been deprecated:
void torrent_handle::filter_piece(int index, bool filter) const;
void torrent_handle::filter_pieces(std::vector<bool> const& pieces) const;
bool torrent_handle::is_piece_filtered(int index) const;
std::vector<bool> torrent_handle::filtered_pieces() const;
void torrent_handle::filter_files(std::vector<bool> const& files) const;
instead, use the piece_priority functions.
* added support for NAT-PMP
* added support for piece priorities. Piece filtering is now set as
a priority
release 0.12
* fixes to make the DHT more compatible
* http seed improvements including error reporting and url encoding issues.
* fixed bug where directories would be left behind when moving storage
in some cases.
* fixed crashing bug when restarting or stopping the DHT.
* added python binding, using boost.python
* improved character conversion on windows when strings are not utf-8.
* metadata extension now respects the private flag in the torrent.
* made the DHT to only be used as a fallback to trackers by default.
* added support for HTTP redirection support for web seeds.
* fixed race condition when accessing a torrent that was checking its
fast resume data.
* fixed a bug in the DHT which could be triggered if the network was
dropped or extremely rare cases.
* if the download rate is limited, web seeds will now only use left-over
bandwidth after all bt peers have used up as much bandwidth as they can.
* added the possibility to have libtorrent resolve the countries of
the peers in torrents.
* improved the bandwidth limiter (it now implements a leaky bucket/node bucket).
* improved the HTTP seed downloader to report accurate progress.
* added more client peer-id signatures to be recognized.
* added support for HTTP servers that skip the CR before the NL at line breaks.
* fixed bug in the HTTP code that only accepted headers case sensitive.
* fixed bug where one of the session constructors didn't initialize boost.filesystem.
* fixed bug when the initial checking of a torrent fails with an exception.
* fixed bug in DHT code which would send incorrect announce messages.
* fixed bug where the http header parser was case sensitive to the header
names.
* Implemented an optmization which frees the piece_picker once a torrent
turns into a seed.
* Added support for uT peer exchange extension, implemented by Massaroddel.
* Modified the quota management to offer better bandwidth balancing
between peers.
* logging now supports multiple sessions (different sessions now log
to different directories).
* fixed random number generator seed problem, generating the same
peer-id for sessions constructed the same second.
* added an option to accept multiple connections from the same IP.
* improved tracker logging.
* moved the file_pool into session. The number of open files is now
limited per session.
* fixed uninitialized private flag in torrent_info
* fixed long standing issue with file.cpp on windows. Replaced the low level
io functions used on windows.
* made it possible to associate a name with torrents without metadata.
* improved http-downloading performance by requesting entire pieces via
http.
* added plugin interface for extensions. And changed the interface for
enabling extensions.
release 0.11
* added support for incorrectly encoded paths in torrent files
(assumes Latin-1 encoding and converts to UTF-8).
* added support for destructing session objects asynchronously.
* fixed bug with file_progress() with files = 0 bytes
* fixed a race condition bug in udp_tracker_connection that could
cause a crash.
* fixed bug occuring when increasing the sequenced download threshold
with max availability lower than previous threshold.
* fixed an integer overflow bug occuring when built with gcc 4.1.x
* fixed crasing bug when closing while checking a torrent
* fixed bug causing a crash with a torrent with piece length 0
* added an extension to the DHT network protocol to support the
exchange of nodes with IPv6 addresses.
* modified the ip_filter api slightly to support IPv6
* modified the api slightly to make sequenced download threshold
a per torrent-setting.
* changed the address type to support IPv6
* fixed bug in piece picker which would not behave as
expected with regard to sequenced download threshold.
* fixed bug with file_progress() with files > 2 GB.
* added --enable-examples option to configure script.
* fixed problem with the resource distribution algorithm
(controlling e.g upload/download rates).
* fixed incorrect asserts in storage related to torrents with
zero-sized files.
* added support for trackerless torrents (with kademlia DHT).
* support for torrents with the private flag set.
* support for torrents containing bootstrap nodes for the
DHT network.
* fixed problem with the configure script on FreeBSD.
* limits the pipelining used on url-seeds.
* fixed problem where the shutdown always would delay for
session_settings::stop_tracker_timeout seconds.
* session::listen_on() won't reopen the socket in case the port and
interface is the same as the one currently in use.
* added http proxy support for web seeds.
* fixed problem where upload and download stats could become incorrect
in case of high cpu load.
* added more clients to the identifiable list.
* fixed fingerprint parser to cope with latest Mainline versions.
release 0.10
* fixed a bug where the requested number of peers in a tracker request could
be too big.
* fixed a bug where empty files were not created in full allocation mode.
* fixed a bug in storage that would, in rare cases, fail to do a
complete check.
* exposed more settings for tweaking parameters in the piece-picker,
downloader and uploader (http_settings replaced by session_settings).
* tweaked default settings to improve high bandwidth transfers.
* improved the piece picker performance and made it possible to download
popular pieces in sequence to improve disk performance.
* added the possibility to control upload and download limits per peer.
* fixed problem with re-requesting skipped pieces when peer was sending pieces
out of fifo-order.
* added support for http seeding (the GetRight protocol)
* renamed identifiers called 'id' in the public interface to support linking
with Objective.C++
* changed the extensions protocol to use the new one, which is also
implemented by uTorrent.
* factorized the peer_connection and added web_peer_connection which is
able to download from http-sources.
* converted the network code to use asio (resulted in slight api changes
dealing with network addresses).
* made libtorrent build in vc7 (patches from Allen Zhao)
* fixed bug caused when binding outgoing connections to a non-local interface.
* add_torrent() will now throw if called while the session object is
being closed.
* added the ability to limit the number of simultaneous half-open
TCP connections. Flags in peer_info has been added.
release 0.9.1
* made the session disable file name checks within the boost.filsystem library
* fixed race condition in the sockets
* strings that are invalid utf-8 strings are now decoded with the
local codepage on windows
* added the ability to build libtorrent both as a shared library
* client_test can now monitor a directory for torrent files and automatically
start and stop downloads while running
* fixed problem with file_size() when building on windows with unicode support
* added a new torrent state, allocating
* added a new alert, metadata_failed_alert
* changed the interface to session::add_torrent for some speed optimizations.
* greatly improved the command line control of the example client_test.
* fixed bug where upload rate limit was not being applied.
* files that are being checked will no longer stall files that don't need
checking.
* changed the way libtorrent identifies support for its excentions
to look for 'ext' at the end of the peer-id.
* improved performance by adding a circle buffer for the send buffer.
* fixed bugs in the http tracker connection when using an http proxy.
* fixed problem with storage's file pool when creating torrents and then
starting to seed them.
* hard limit on remote request queue and timeout on requests (a timeout
triggers rerequests). This makes libtorrent work much better with
"broken" clients like BitComet which may ignore requests.
Initial release 0.9
* multitracker support
* serves multiple torrents on a single port and a single thread
* supports http proxies and proxy authentication
* gzipped tracker-responses
* block level piece picker
* queues torrents for file check, instead of checking all of them in parallel
* uses separate threads for checking files and for main downloader
* upload and download rate limits
* piece-wise, unordered, incremental file allocation
* fast resume support
* supports files > 2 gigabytes
* supports the no_peer_id=1 extension
* support for udp-tracker protocol
* number of connections limit
* delays sending have messages
* can resume pieces downloaded in any order
* adjusts the length of the request queue depending on download rate
* supports compact=1
* selective downloading
* ip filter

3
libtorrent/NEWS Normal file
View file

@ -0,0 +1,3 @@
initial release of libtorrent 0.9

25
libtorrent/README Normal file
View file

@ -0,0 +1,25 @@
libtorrent is a C++ library that aims to be a good alternative to all the
other bittorrent implementations around. It is a
library and not a full featured client, although it comes with a working
example client.
The main goals of libtorrent are:
* to be cpu efficient
* to be memory efficient
* to be very easy to use
See docs/manual.html for more detailed build and usage instructions.
To build with autotools, run:
./configure
Followed by
make
When libtorrent is built, finish off by running the tests:
make check

View file

@ -0,0 +1,3 @@
Documentation covering building and using the python binding for libtorrent
is located in the main doc directory. See docs/python_binding.html

View file

@ -0,0 +1,29 @@
import python ;
use-project /torrent : ../.. ;
python-extension libtorrent
: src/module.cpp
src/big_number.cpp
src/fingerprint.cpp
src/utility.cpp
src/session.cpp
src/entry.cpp
src/torrent_info.cpp
src/filesystem.cpp
src/torrent_handle.cpp
src/torrent_status.cpp
src/session_settings.cpp
src/version.cpp
src/alert.cpp
src/datetime.cpp
src/extensions.cpp
src/peer_plugin.cpp
src/docstrings.cpp
src/torrent.cpp
src/peer_info.cpp
/torrent//torrent
/boost/python//boost_python
: <include>src
;

View file

@ -0,0 +1,355 @@
#!/usr/bin/python
# Copyright Daniel Wallin 2006. Use, modification and distribution is
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import sys
import libtorrent as lt
import time
import os.path
import sys
class WindowsConsole:
def __init__(self):
self.console = Console.getconsole()
def clear(self):
self.console.page()
def write(self, str):
self.console.write(str)
def sleep_and_input(self, seconds):
time.sleep(seconds)
if msvcrt.kbhit():
return msvcrt.getch()
return None
class UnixConsole:
def __init__(self):
self.fd = sys.stdin
self.old = termios.tcgetattr(self.fd.fileno())
new = termios.tcgetattr(self.fd.fileno())
new[3] = new[3] & ~termios.ICANON
new[6][termios.VTIME] = 0
new[6][termios.VMIN] = 1
termios.tcsetattr(self.fd.fileno(), termios.TCSADRAIN, new)
sys.exitfunc = self._onexit
def _onexit(self):
termios.tcsetattr(self.fd.fileno(), termios.TCSADRAIN, self.old)
def clear(self):
sys.stdout.write('\033[2J\033[0;0H')
sys.stdout.flush()
def write(self, str):
sys.stdout.write(str)
sys.stdout.flush()
def sleep_and_input(self, seconds):
read,_,_ = select.select([self.fd.fileno()], [], [], seconds)
if len(read) > 0:
return self.fd.read(1)
return None
if os.name == 'nt':
import Console
import msvcrt
else:
import termios
import select
class PythonExtension(lt.torrent_plugin):
def __init__(self, alerts):
lt.torrent_plugin.__init__(self)
self.alerts = alerts
self.alerts.append('PythonExtension')
self.count = 0
def on_piece_pass(self, index):
self.alerts.append('got piece %d' % index)
def on_piece_failed(self, index):
self.alerts.append('failed piece %d' % index)
def tick(self):
self.count += 1
if self.count >= 10:
self.count = 0
self.alerts.append('PythonExtension tick')
def write_line(console, line):
console.write(line)
def add_suffix(val):
prefix = ['B', 'kB', 'MB', 'GB', 'TB']
for i in range(len(prefix)):
if abs(val) < 1000:
if i == 0:
return '%5.3g%s' % (val, prefix[i])
else:
return '%4.3g%s' % (val, prefix[i])
val /= 1000
return '%6.3gPB' % val
def progress_bar(progress, width):
progress_chars = int(progress * width + 0.5)
return progress_chars * '#' + (width - progress_chars) * '-'
def print_peer_info(console, peers):
out = ' down (total ) up (total ) q r flags block progress client\n'
for p in peers:
out += '%s/s ' % add_suffix(p.down_speed)
out += '(%s) ' % add_suffix(p.total_download)
out += '%s/s ' % add_suffix(p.up_speed)
out += '(%s) ' % add_suffix(p.total_upload)
out += '%2d ' % p.download_queue_length
out += '%2d ' % p.upload_queue_length
if p.flags & lt.peer_info.interesting: out += 'I'
else: out += '.'
if p.flags & lt.peer_info.choked: out += 'C'
else: out += '.'
if p.flags & lt.peer_info.remote_interested: out += 'i'
else: out += '.'
if p.flags & lt.peer_info.remote_choked: out += 'c'
else: out += '.'
if p.flags & lt.peer_info.supports_extensions: out += 'e'
else: out += '.'
if p.flags & lt.peer_info.local_connection: out += 'l'
else: out += 'r'
out += ' '
if p.downloading_piece_index >= 0:
out += progress_bar(float(p.downloading_progress) / p.downloading_total, 15)
else:
out += progress_bar(0, 15)
out += ' '
if p.flags & lt.peer_info.handshake:
id = 'waiting for handshake'
elif p.flags & lt.peer_info.connecting:
id = 'connecting to peer'
elif p.flags & lt.peer_info.queued:
id = 'queued'
else:
id = p.client
out += '%s\n' % id[:10]
write_line(console, out)
def print_download_queue(console, download_queue):
out = ""
for e in download_queue:
out += '%4d: [' % e['piece_index'];
for b in e['blocks']:
s = b['state']
if s == 3:
out += '#'
elif s == 2:
out += '='
elif s == 1:
out += '-'
else:
out += ' '
out += ']\n'
write_line(console, out)
def main():
from optparse import OptionParser
parser = OptionParser()
parser.add_option('-p', '--port',
type='int', help='set listening port')
parser.add_option('-r', '--ratio',
type='float', help='set the preferred upload/download ratio. 0 means infinite. Values smaller than 1 are clamped to 1')
parser.add_option('-d', '--max-download-rate',
type='float', help='the maximum download rate given in kB/s. 0 means infinite.')
parser.add_option('-u', '--max-upload-rate',
type='float', help='the maximum upload rate given in kB/s. 0 means infinite.')
parser.add_option('-s', '--save-path',
type='string', help='the path where the downloaded file/folder should be placed.')
parser.add_option('-a', '--allocation-mode',
type='string', help='sets mode used for allocating the downloaded files on disk. Possible options are [full | compact]')
parser.set_defaults(
port=6881
, ratio=0
, max_download_rate=0
, max_upload_rate=0
, save_path='./'
, allocation_mode='compact'
)
(options, args) = parser.parse_args()
if options.port < 0 or options.port > 65525:
options.port = 6881
options.max_upload_rate *= 1000
options.max_download_rate *= 1000
if options.max_upload_rate <= 0:
options.max_upload_rate = -1
if options.max_download_rate <= 0:
options.max_download_rate = -1
compact_allocation = options.allocation_mode == 'compact'
settings = lt.session_settings()
settings.user_agent = 'python_client/' + lt.version
ses = lt.session()
ses.set_download_rate_limit(int(options.max_download_rate))
ses.set_upload_rate_limit(int(options.max_upload_rate))
ses.listen_on(options.port, options.port + 10)
ses.set_settings(settings)
ses.set_severity_level(lt.alert.severity_levels.info)
# ses.add_extension(lt.create_ut_pex_plugin);
# ses.add_extension(lt.create_metadata_plugin);
handles = []
alerts = []
# Extensions
# ses.add_extension(lambda x: PythonExtension(alerts))
for f in args:
e = lt.bdecode(open(f, 'rb').read())
info = lt.torrent_info(e)
print 'Adding \'%s\'...' % info.name()
try:
resume_data = lt.bdecode(open(
os.path.join(options.save_path, info.name() + '.fastresume'), 'rb').read())
except:
resume_data = None
h = ses.add_torrent(info, options.save_path,
resume_data=resume_data, compact_mode=compact_allocation)
handles.append(h)
h.set_max_connections(60)
h.set_max_uploads(-1)
h.set_ratio(options.ratio)
h.set_sequenced_download_threshold(15)
if os.name == 'nt':
console = WindowsConsole()
else:
console = UnixConsole()
alive = True
while alive:
console.clear()
out = ''
for h in handles:
if h.has_metadata():
name = h.torrent_info().name()[:40]
else:
name = '-'
out += 'name: %-40s\n' % name
s = h.status()
if s.state != lt.torrent_status.seeding:
state_str = ['queued', 'checking', 'connecting', 'downloading metadata', \
'downloading', 'finished', 'seeding', 'allocating']
out += state_str[s.state] + ' '
out += '%5.4f%% ' % (s.progress*100)
out += progress_bar(s.progress, 49)
out += '\n'
out += 'total downloaded: %d Bytes\n' % s.total_done
out += 'peers: %d seeds: %d distributed copies: %d\n' % \
(s.num_peers, s.num_seeds, s.distributed_copies)
out += '\n'
out += 'download: %s/s (%s) ' \
% (add_suffix(s.download_rate), add_suffix(s.total_download))
out += 'upload: %s/s (%s) ' \
% (add_suffix(s.upload_rate), add_suffix(s.total_upload))
out += 'ratio: %s\n' % '0'
if s.state != lt.torrent_status.seeding:
out += 'info-hash: %s\n' % h.info_hash()
out += 'next announce: %s\n' % s.next_announce
out += 'tracker: %s\n' % s.current_tracker
write_line(console, out)
print_peer_info(console, h.get_peer_info())
print_download_queue(console, h.get_download_queue())
if True and s.state != lt.torrent_status.seeding:
out = '\n'
fp = h.file_progress()
ti = h.torrent_info()
for f,p in zip(ti.files(), fp):
out += progress_bar(p, 20)
out += ' ' + f.path + '\n'
write_line(console, out)
write_line(console, 76 * '-' + '\n')
write_line(console, '(q)uit), (p)ause), (u)npause), (r)eannounce\n')
write_line(console, 76 * '-' + '\n')
while 1:
a = ses.pop_alert()
if not a: break
alerts.append(a)
if len(alerts) > 8:
del alerts[:len(alerts) - 8]
for a in alerts:
if type(a) == str:
write_line(console, a + '\n')
else:
write_line(console, a.msg() + '\n')
c = console.sleep_and_input(0.5)
if not c:
continue
if c == 'r':
for h in handles: h.force_reannounce()
elif c == 'q':
alive = False
elif c == 'p':
for h in handles: h.pause()
elif c == 'u':
for h in handles: h.resume()
for h in handles:
if not h.is_valid() or not h.has_metadata():
continue
h.pause()
data = lt.bencode(h.write_resume_data())
open(os.path.join(options.save_path, h.torrent_info().name() + '.fastresume'), 'wb').write(data)
main()

View file

@ -0,0 +1,24 @@
#!/usr/bin/python
import libtorrent as lt
import time
ses = lt.session()
ses.listen_on(6881, 6891)
e = lt.bdecode(open("test.torrent", 'rb').read())
info = lt.torrent_info(e)
h = ses.add_torrent(info, "./", compact_mode = True)
while (not h.is_seed()):
s = h.status()
state_str = ['queued', 'checking', 'connecting', 'downloading metadata', \
'downloading', 'finished', 'seeding', 'allocating']
print '%.2f%% complete (down: %.1f kb/s up: %.1f kB/s peers: %d) %s' % \
(s.progress * 100, s.download_rate / 1000, s.upload_rate / 1000, \
s.num_peers, state_str[s.state])
time.sleep(1)

View file

@ -0,0 +1,162 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/alert.hpp>
#include <libtorrent/alert_types.hpp>
#include <boost/python.hpp>
using namespace boost::python;
using namespace libtorrent;
extern char const* alert_doc;
extern char const* alert_msg_doc;
extern char const* alert_severity_doc;
extern char const* listen_failed_alert_doc;
extern char const* file_error_alert_doc;
extern char const* tracker_announce_alert_doc;
extern char const* tracker_alert_doc;
extern char const* tracker_reply_alert_doc;
extern char const* tracker_warning_alert_doc;
extern char const* url_seed_alert_doc;
extern char const* hash_failed_alert_doc;
extern char const* peer_ban_alert_doc;
extern char const* peer_error_alert_doc;
extern char const* invalid_request_alert_doc;
extern char const* peer_request_doc;
extern char const* torrent_finished_alert_doc;
extern char const* metadata_failed_alert_doc;
extern char const* metadata_received_alert_doc;
extern char const* fastresume_rejected_alert_doc;
void bind_alert()
{
using boost::noncopyable;
{
scope alert_scope = class_<alert, noncopyable>("alert", alert_doc, no_init)
.def(
"msg", &alert::msg, return_value_policy<copy_const_reference>()
, alert_msg_doc
)
.def("severity", &alert::severity, alert_severity_doc)
.def(
"__str__", &alert::msg, return_value_policy<copy_const_reference>()
, alert_msg_doc
)
;
enum_<alert::severity_t>("severity_levels")
.value("debug", alert::debug)
.value("info", alert::info)
.value("warning", alert::warning)
.value("critical", alert::critical)
.value("fatal", alert::fatal)
.value("none", alert::none)
;
}
class_<listen_failed_alert, bases<alert>, noncopyable>(
"listen_failed_alert", listen_failed_alert_doc, no_init
);
class_<file_error_alert, bases<alert>, noncopyable>(
"file_error_alert", file_error_alert_doc, no_init
)
.def_readonly("handle", &file_error_alert::handle)
;
class_<tracker_announce_alert, bases<alert>, noncopyable>(
"tracker_announce_alert", tracker_announce_alert_doc, no_init
)
.def_readonly("handle", &tracker_announce_alert::handle)
;
class_<tracker_alert, bases<alert>, noncopyable>(
"tracker_alert", tracker_alert_doc, no_init
)
.def_readonly("handle", &tracker_alert::handle)
.def_readonly("times_in_row", &tracker_alert::times_in_row)
.def_readonly("status_code", &tracker_alert::status_code)
;
class_<tracker_reply_alert, bases<alert>, noncopyable>(
"tracker_reply_alert", tracker_reply_alert_doc, no_init
)
.def_readonly("handle", &tracker_reply_alert::handle)
;
class_<tracker_warning_alert, bases<alert>, noncopyable>(
"tracker_warning_alert", tracker_warning_alert_doc, no_init
)
.def_readonly("handle", &tracker_warning_alert::handle)
;
class_<url_seed_alert, bases<alert>, noncopyable>(
"url_seed_alert", url_seed_alert_doc, no_init
)
.def_readonly("url", &url_seed_alert::url)
;
class_<hash_failed_alert, bases<alert>, noncopyable>(
"hash_failed_alert", hash_failed_alert_doc, no_init
)
.def_readonly("handle", &hash_failed_alert::handle)
.def_readonly("piece_index", &hash_failed_alert::piece_index)
;
class_<peer_ban_alert, bases<alert>, noncopyable>(
"peer_ban_alert", peer_ban_alert_doc, no_init
)
.def_readonly("ip", &peer_ban_alert::ip)
.def_readonly("handle", &peer_ban_alert::handle)
;
class_<peer_error_alert, bases<alert>, noncopyable>(
"peer_error_alert", peer_error_alert_doc, no_init
)
.def_readonly("ip", &peer_error_alert::ip)
.def_readonly("pid", &peer_error_alert::pid)
;
class_<invalid_request_alert, bases<alert>, noncopyable>(
"invalid_request_alert", invalid_request_alert_doc, no_init
)
.def_readonly("handle", &invalid_request_alert::handle)
.def_readonly("ip", &invalid_request_alert::ip)
.def_readonly("request", &invalid_request_alert::request)
.def_readonly("pid", &invalid_request_alert::pid)
;
class_<peer_request>("peer_request", peer_request_doc)
.def_readonly("piece", &peer_request::piece)
.def_readonly("start", &peer_request::start)
.def_readonly("length", &peer_request::length)
.def(self == self)
;
class_<torrent_finished_alert, bases<alert>, noncopyable>(
"torrent_finished_alert", torrent_finished_alert_doc, no_init
)
.def_readonly("handle", &torrent_finished_alert::handle)
;
class_<metadata_failed_alert, bases<alert>, noncopyable>(
"metadata_failed_alert", metadata_failed_alert_doc, no_init
)
.def_readonly("handle", &metadata_failed_alert::handle)
;
class_<metadata_received_alert, bases<alert>, noncopyable>(
"metadata_received_alert", metadata_received_alert_doc, no_init
)
.def_readonly("handle", &metadata_received_alert::handle)
;
class_<fastresume_rejected_alert, bases<alert>, noncopyable>(
"fastresume_rejected_alert", fastresume_rejected_alert_doc, no_init
)
.def_readonly("handle", &fastresume_rejected_alert::handle)
;
}

View file

@ -0,0 +1,20 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/peer_id.hpp>
#include <boost/python.hpp>
void bind_big_number()
{
using namespace boost::python;
using namespace libtorrent;
class_<big_number>("big_number")
.def(self == self)
.def(self != self)
.def(self < self)
.def(self_ns::str(self))
;
}

View file

@ -0,0 +1,5 @@
// Copyright Daniel Wallin 2007. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View file

@ -0,0 +1,81 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include "optional.hpp"
#include <boost/version.hpp>
using namespace boost::python;
#if BOOST_VERSION < 103400
// From Boost 1.34
object import(str name)
{
// should be 'char const *' but older python versions don't use 'const' yet.
char *n = extract<char *>(name);
handle<> module(borrowed(PyImport_ImportModule(n)));
return object(module);
}
#endif
object datetime_timedelta;
object datetime_datetime;
struct time_duration_to_python
{
static PyObject* convert(boost::posix_time::time_duration const& d)
{
object result = datetime_timedelta(
0 // days
, 0 // seconds
, d.total_microseconds()
);
return incref(result.ptr());
}
};
struct ptime_to_python
{
static PyObject* convert(boost::posix_time::ptime const& pt)
{
boost::gregorian::date date = pt.date();
boost::posix_time::time_duration td = pt.time_of_day();
object result = datetime_datetime(
(int)date.year()
, (int)date.month()
, (int)date.day()
, td.hours()
, td.minutes()
, td.seconds()
);
return incref(result.ptr());
}
};
void bind_datetime()
{
object datetime = import("datetime").attr("__dict__");
datetime_timedelta = datetime["timedelta"];
datetime_datetime = datetime["datetime"];
to_python_converter<
boost::posix_time::time_duration
, time_duration_to_python
>();
to_python_converter<
boost::posix_time::ptime
, ptime_to_python
>();
optional_to_python<boost::posix_time::ptime>();
}

View file

@ -0,0 +1,266 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// -- torrent_status --------------------------------------------------------
char const* torrent_status_doc =
"Represents the current status for a torrent.\n"
"Returned by `torrent_handle.status()`.";
char const* torrent_status_state_doc =
"The torrents current task. One of `torrent_status.states`.";
char const* torrent_status_paused_doc =
"Indicates if this torrent is paused or not.";
char const* torrent_status_progress_doc =
"A value in the range [0, 1], that represents the progress of\n"
"the torrent's current task.";
char const* torrent_status_next_announce_doc =
"The time until the torrent will announce itself to the\n"
"tracker. An instance of `datetime.timedelta`.";
char const* torrent_status_announce_interval_doc =
"The interval at which the torrent will reannounce itself to the\n"
"tracker. An instance of `datetime.timedelta`.";
char const* torrent_status_current_tracker_doc =
"The URL of the last working tracker. If no tracker request has\n"
"been successful yet, it's set to an empty string.";
char const* torrent_status_total_download_doc = "";
char const* torrent_status_total_upload_doc = "";
char const* torrent_status_total_payload_download_doc = "";
char const* torrent_status_total_payload_upload_doc = "";
char const* torrent_status_total_failed_bytes_doc = "";
// -- session_status --------------------------------------------------------
char const* session_status_doc =
"";
char const* session_status_has_incoming_connections_doc =
"";
char const* session_status_upload_rate_doc =
"";
char const* session_status_download_rate_doc =
"";
char const* session_status_payload_upload_rate_doc =
"";
char const* session_status_payload_download_rate_doc =
"";
char const* session_status_total_download_doc =
"";
char const* session_status_total_upload_doc =
"";
char const* session_status_total_payload_download_doc =
"";
char const* session_status_total_payload_upload_doc =
"";
char const* session_status_num_peers_doc =
"";
char const* session_status_dht_nodes_doc =
"";
char const* session_status_cache_nodes_doc =
"";
char const* session_status_dht_torrents_doc =
"";
// -- session ---------------------------------------------------------------
char const* session_doc =
"";
char const* session_init_doc =
"The `fingerprint` is a short string that will be used in\n"
"the peer-id to identify the client and the client's version.\n"
"For more details see the `fingerprint` class.\n"
"The constructor that only takes a fingerprint will not open\n"
"a listen port for the session, to get it running you'll have\n"
"to call `session.listen_on()`.";
char const* session_listen_on_doc =
"";
char const* session_is_listening_doc =
"";
char const* session_listen_port_doc =
"";
char const* session_status_m_doc =
"Returns an instance of `session_status` with session wide-statistics\n"
"and status";
char const* session_start_dht_doc =
"";
char const* session_stop_dht_doc =
"";
char const* session_dht_state_doc =
"";
char const* session_add_torrent_doc =
"Adds a new torrent to the session. Return a `torrent_handle`.\n"
"\n"
":Parameters:\n"
" - `torrent_info`: `torrent_info` instance representing the torrent\n"
" you want to add.\n"
" - `save_path`: The path to the directory where files will be saved.\n"
" - `resume_data (optional)`: The resume data for this torrent, as decoded\n"
" with `bdecode()`. This can be acquired from a running torrent with\n"
" `torrent_handle.write_resume_data()`.\n"
" - `compact_mode (optional)`: If set to true (default), the storage\n"
" will grow as more pieces are downloaded, and pieces are rearranged\n"
" to finally be in their correct places once the entire torrent has\n"
" been downloaded. If it is false, the entire storage is allocated\n"
" before download begins. I.e. the files contained in the torrent\n"
" are filled with zeros, and each downloaded piece is put in its\n"
" final place directly when downloaded.\n"
" - `block_size (optional)`: Sets the preferred request size, i.e.\n"
" the number of bytes to request from a peer at a time. This block size\n"
" must be a divisor of the piece size, and since the piece size is an\n"
" even power of 2, so must the block size be. If the block size given\n"
" here turns out to be greater than the piece size, it will simply be\n"
" clamped to the piece size.\n"
"\n"
":Exceptions:\n"
" - `duplicate_torrent`: If the torrent you are trying to add already\n"
" exists in the session (is either queued for checking, being checked\n"
" or downloading) `add_torrent()` will throw `duplicate_torrent`.\n";
char const* session_remove_torrent_doc =
"Close all peer connections associated with the torrent and tell the\n"
"tracker that we've stopped participating in the swarm.";
char const* session_set_download_rate_limit_doc =
"";
char const* session_set_upload_rate_limit_doc =
"";
char const* session_set_max_uploads_doc =
"";
char const* session_set_max_connections_doc =
"";
char const* session_set_max_half_open_connections_doc =
"Sets the maximum number of half-open connections libtorrent will\n"
"have when connecting to peers. A half-open connection is one where\n"
"connect() has been called, but the connection still hasn't been\n"
"established (nor failed). Windows XP Service Pack 2 sets a default,\n"
"system wide, limit of the number of half-open connections to 10. So, \n"
"this limit can be used to work nicer together with other network\n"
"applications on that system. The default is to have no limit, and passing\n"
"-1 as the limit, means to have no limit. When limiting the number of\n"
"simultaneous connection attempts, peers will be put in a queue waiting\n"
"for their turn to get connected.";
char const* session_set_settings_doc =
"";
char const* session_set_severity_level_doc =
"";
char const* session_pop_alert_doc =
"";
// -- alert -----------------------------------------------------------------
char const* alert_doc =
"Base class for all concrete alert classes.";
char const* alert_msg_doc =
"Returns a string describing this alert.";
char const* alert_severity_doc =
"Returns the severity level for this alert, one of `alert.severity_levels`.";
char const* listen_failed_alert_doc =
"This alert is generated when none of the ports, given in the\n"
"port range, to `session` can be opened for listening. This alert\n"
"is generated as severity level `alert.severity_levels.fatal`.";
char const* file_error_alert_doc =
"If the storage fails to read or write files that it needs access\n"
"to, this alert is generated and the torrent is paused. It is\n"
"generated as severity level `alert.severity_levels.fatal`.";
char const* tracker_announce_alert_doc =
"This alert is generated each time a tracker announce is sent\n"
"(or attempted to be sent). It is generated at severity level `alert.severity_levels.info`.";
char const* tracker_alert_doc =
"This alert is generated on tracker time outs, premature\n"
"disconnects, invalid response or a HTTP response other than\n"
"\"200 OK\". From the alert you can get the handle to the torrent\n"
"the tracker belongs to. This alert is generated as severity level\n"
"`alert.severity_levels.warning`.";
char const* tracker_reply_alert_doc =
"This alert is only for informational purpose. It is generated when\n"
"a tracker announce succeeds. It is generated with severity level\n"
"`alert.severity_levels.info`.";
char const* tracker_warning_alert_doc =
"This alert is triggered if the tracker reply contains a warning\n"
"field. Usually this means that the tracker announce was successful\n"
", but the tracker has a message to the client. The message string in\n"
"the alert will contain the warning message from the tracker. It is\n"
"generated with severity level `alert.severity_levels.warning`.";
char const* url_seed_alert_doc =
"This alert is generated when a HTTP seed name lookup fails. This\n"
"alert is generated as severity level `alert.severity_levels.warning`.";
char const* hash_failed_alert_doc =
"This alert is generated when a finished piece fails its hash check.\n"
"You can get the handle to the torrent which got the failed piece\n"
"and the index of the piece itself from the alert. This alert is\n"
"generated as severity level `alert.severity_levels.info`.";
char const* peer_ban_alert_doc =
"This alert is generated when a peer is banned because it has sent\n"
"too many corrupt pieces to us. It is generated at severity level\n"
"`alert.severity_levels.info`. The handle member is a `torrent_handle` to the torrent that\n"
"this peer was a member of.";
char const* peer_error_alert_doc =
"This alert is generated when a peer sends invalid data over the\n"
"peer-peer protocol. The peer will be disconnected, but you get its\n"
"ip address from the alert, to identify it. This alert is generated\n"
"is severity level `alert.severity_levels.debug`.";
char const* invalid_request_alert_doc =
"This is a debug alert that is generated by an incoming invalid\n"
"piece request. The handle is a handle to the torrent the peer\n"
"is a member of. Ip is the address of the peer and the request is\n"
"the actual incoming request from the peer. The alert is generated\n"
"as severity level `alert.severity_levels.debug`.";
char const* peer_request_doc =
"The `peer_request` contains the values the client sent in its\n"
"request message. ``piece`` is the index of the piece it want data\n"
"from, ``start`` is the offset within the piece where the data should be\n"
"read, and ``length`` is the amount of data it wants.";
char const* torrent_finished_alert_doc =
"This alert is generated when a torrent switches from being a\n"
"downloader to a seed. It will only be generated once per torrent.\n"
"It contains a `torrent_handle` to the torrent in question. This alert\n"
"is generated as severity level `alert.severity_levels.info`.";
char const* metadata_failed_alert_doc =
"This alert is generated when the metadata has been completely\n"
"received and the info-hash failed to match it. i.e. the\n"
"metadata that was received was corrupt. libtorrent will\n"
"automatically retry to fetch it in this case. This is only\n"
"relevant when running a torrent-less download, with the metadata\n"
"extension provided by libtorrent. It is generated at severity\n"
"level `alert.severity_levels.info`.";
char const* metadata_received_alert_doc =
"This alert is generated when the metadata has been completely\n"
"received and the torrent can start downloading. It is not generated\n"
"on torrents that are started with metadata, but only those that\n"
"needs to download it from peers (when utilizing the libtorrent\n"
"extension). It is generated at severity level `alert.severity_levels.info`.";
char const* fastresume_rejected_alert_doc =
"This alert is generated when a fastresume file has been passed\n"
"to `session.add_torrent` but the files on disk did not match the\n"
"fastresume file. The string explains the reason why the resume\n"
"file was rejected. It is generated at severity level `alert.severity_levels.warning`.";

View file

@ -0,0 +1,132 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/session.hpp>
#include <boost/python.hpp>
using namespace boost::python;
using namespace libtorrent;
struct entry_to_python
{
static object convert(entry::list_type const& l)
{
list result;
for (entry::list_type::const_iterator i(l.begin()), e(l.end()); i != e; ++i)
{
result.append(*i);
}
return result;
}
static object convert(entry::dictionary_type const& d)
{
dict result;
for (entry::dictionary_type::const_iterator i(d.begin()), e(d.end()); i != e; ++i)
result[i->first] = i->second;
return result;
}
static object convert0(entry const& e)
{
switch (e.type())
{
case entry::int_t:
return object(e.integer());
case entry::string_t:
return object(e.string());
case entry::list_t:
return convert(e.list());
case entry::dictionary_t:
return convert(e.dict());
default:
return object();
}
}
static PyObject* convert(entry const& e)
{
return incref(convert0(e).ptr());
}
};
struct entry_from_python
{
entry_from_python()
{
converter::registry::push_back(
&convertible, &construct, type_id<entry>()
);
}
static void* convertible(PyObject* e)
{
return e;
}
static entry construct0(object e)
{
if (extract<dict>(e).check())
{
dict d = extract<dict>(e);
list items(d.items());
std::size_t length = extract<std::size_t>(items.attr("__len__")());
entry result(entry::dictionary_t);
for (std::size_t i = 0; i < length; ++i)
{
result.dict().insert(
std::make_pair(
extract<char const*>(items[i][0])()
, construct0(items[i][1])
)
);
}
return result;
}
else if (extract<list>(e).check())
{
list l = extract<list>(e);
std::size_t length = extract<std::size_t>(l.attr("__len__")());
entry result(entry::list_t);
for (std::size_t i = 0; i < length; ++i)
{
result.list().push_back(construct0(l[i]));
}
return result;
}
else if (extract<str>(e).check())
{
return entry(extract<std::string>(e)());
}
else if (extract<entry::integer_type>(e).check())
{
return entry(extract<entry::integer_type>(e)());
}
return entry();
}
static void construct(PyObject* e, converter::rvalue_from_python_stage1_data* data)
{
void* storage = ((converter::rvalue_from_python_storage<entry>*)data)->storage.bytes;
new (storage) entry(construct0(object(borrowed(e))));
data->convertible = storage;
}
};
void bind_entry()
{
to_python_converter<entry, entry_to_python>();
entry_from_python();
}

View file

@ -0,0 +1,148 @@
// Copyright Daniel Wallin, Arvid Norberg 2007. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/extensions.hpp>
#include <libtorrent/entry.hpp>
#include <libtorrent/peer_request.hpp>
#include <libtorrent/peer_connection.hpp>
#include <libtorrent/extensions/ut_pex.hpp>
#include <libtorrent/extensions/metadata_transfer.hpp>
#include <boost/python.hpp>
#include "gil.hpp"
using namespace boost::python;
using namespace libtorrent;
namespace
{
struct torrent_plugin_wrap : torrent_plugin, wrapper<torrent_plugin>
{
boost::shared_ptr<peer_plugin> new_connection(peer_connection* p)
{
lock_gil lock;
if (override f = this->get_override("new_connection"))
return f(ptr(p));
return torrent_plugin::new_connection(p);
}
boost::shared_ptr<peer_plugin> default_new_connection(peer_connection* p)
{
return this->torrent_plugin::new_connection(p);
}
void on_piece_pass(int index)
{
lock_gil lock;
if (override f = this->get_override("on_piece_pass"))
f(index);
else
torrent_plugin::on_piece_pass(index);
}
void default_on_piece_pass(int index)
{
this->torrent_plugin::on_piece_pass(index);
}
void on_piece_failed(int index)
{
lock_gil lock;
if (override f = this->get_override("on_piece_failed"))
f(index);
else
torrent_plugin::on_piece_failed(index);
}
void default_on_piece_failed(int index)
{
return this->torrent_plugin::on_piece_failed(index);
}
void tick()
{
lock_gil lock;
if (override f = this->get_override("tick"))
f();
else
torrent_plugin::tick();
}
void default_tick()
{
return this->torrent_plugin::tick();
}
bool on_pause()
{
lock_gil lock;
if (override f = this->get_override("on_pause"))
return f();
return torrent_plugin::on_pause();
}
bool default_on_pause()
{
return this->torrent_plugin::on_pause();
}
bool on_resume()
{
lock_gil lock;
if (override f = this->get_override("on_resume"))
return f();
return torrent_plugin::on_resume();
}
bool default_on_resume()
{
return this->torrent_plugin::on_resume();
}
};
} // namespace unnamed
void bind_extensions()
{
class_<
torrent_plugin_wrap, boost::shared_ptr<torrent_plugin_wrap>, boost::noncopyable
>("torrent_plugin")
.def(
"new_connection"
, &torrent_plugin::new_connection, &torrent_plugin_wrap::default_new_connection
)
.def(
"on_piece_pass"
, &torrent_plugin::on_piece_pass, &torrent_plugin_wrap::default_on_piece_pass
)
.def(
"on_piece_failed"
, &torrent_plugin::on_piece_failed, &torrent_plugin_wrap::default_on_piece_failed
)
.def(
"tick"
, &torrent_plugin::tick, &torrent_plugin_wrap::default_tick
)
.def(
"on_pause"
, &torrent_plugin::on_pause, &torrent_plugin_wrap::default_on_pause
)
.def(
"on_resume"
, &torrent_plugin::on_resume, &torrent_plugin_wrap::default_on_resume
);
// TODO move to it's own file
class_<peer_connection, boost::noncopyable>("peer_connection", no_init);
def("create_ut_pex_plugin", create_ut_pex_plugin);
def("create_metadata_plugin", create_metadata_plugin);
}

View file

@ -0,0 +1,51 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include <boost/filesystem/path.hpp>
using namespace boost::python;
struct path_to_python
{
static PyObject* convert(boost::filesystem::path const& p)
{
return incref(object(p.string()).ptr());
}
};
struct path_from_python
{
path_from_python()
{
converter::registry::push_back(
&convertible, &construct, type_id<boost::filesystem::path>()
);
}
static void* convertible(PyObject* x)
{
return PyString_Check(x) ? x : 0;
}
static void construct(PyObject* x, converter::rvalue_from_python_stage1_data* data)
{
void* storage = ((converter::rvalue_from_python_storage<
boost::filesystem::path
>*)data)->storage.bytes;
new (storage) boost::filesystem::path(PyString_AsString(x));
data->convertible = storage;
}
};
void bind_filesystem()
{
to_python_converter<boost::filesystem::path, path_to_python>();
path_from_python();
using namespace boost::filesystem;
if (path::default_name_check_writable())
path::default_name_check(no_check);
}

View file

@ -0,0 +1,27 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/fingerprint.hpp>
#include <boost/python.hpp>
void bind_fingerprint()
{
using namespace boost::python;
using namespace libtorrent;
class_<fingerprint>("fingerprint", no_init)
.def(
init<char const*,int,int,int,int>(
(arg("id"), "major", "minor", "revision", "tag")
)
)
.def("__str__", &fingerprint::to_string)
.def_readonly("name", &fingerprint::name)
.def_readonly("major_version", &fingerprint::major_version)
.def_readonly("minor_version", &fingerprint::minor_version)
.def_readonly("revision_version", &fingerprint::revision_version)
.def_readonly("tag_version", &fingerprint::tag_version)
;
}

View file

@ -0,0 +1,144 @@
// Copyright Daniel Wallin 2007. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef GIL_070107_HPP
# define GIL_070107_HPP
# include <boost/python/make_function.hpp>
# include <boost/python/def_visitor.hpp>
# include <boost/python/signature.hpp>
# include <boost/mpl/at.hpp>
//namespace libtorrent { namespace python {
// RAII helper to release GIL.
struct allow_threading_guard
{
allow_threading_guard()
: save(PyEval_SaveThread())
{}
~allow_threading_guard()
{
PyEval_RestoreThread(save);
}
PyThreadState* save;
};
struct lock_gil
{
lock_gil()
: state(PyGILState_Ensure())
{}
~lock_gil()
{
PyGILState_Release(state);
}
PyGILState_STATE state;
};
template <class F, class R>
struct allow_threading
{
allow_threading(F fn)
: fn(fn)
{}
template <class A0>
R operator()(A0& a0)
{
allow_threading_guard guard;
return (a0.*fn)();
}
template <class A0, class A1>
R operator()(A0& a0, A1& a1)
{
allow_threading_guard guard;
return (a0.*fn)(a1);
}
template <class A0, class A1, class A2>
R operator()(A0& a0, A1& a1, A2& a2)
{
allow_threading_guard guard;
return (a0.*fn)(a1,a2);
}
template <class A0, class A1, class A2, class A3>
R operator()(A0& a0, A1& a1, A2& a2, A3& a3)
{
allow_threading_guard guard;
return (a0.*fn)(a1,a2,a3);
}
template <class A0, class A1, class A2, class A3, class A4>
R operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
{
allow_threading_guard guard;
return (a0.*fn)(a1,a2,a3,a4);
}
template <class A0, class A1, class A2, class A3, class A4, class A5>
R operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5)
{
allow_threading_guard guard;
return (a0.*fn)(a1,a2,a3,a4,a5);
}
F fn;
};
template <class F>
struct visitor : boost::python::def_visitor<visitor<F> >
{
visitor(F fn)
: fn(fn)
{}
template <class Class, class Options, class Signature>
void visit_aux(
Class& cl, char const* name
, Options const& options, Signature const& signature) const
{
typedef typename boost::mpl::at_c<Signature,0>::type return_type;
cl.def(
name
, boost::python::make_function(
allow_threading<F, return_type>(fn)
, options.policies()
, options.keywords()
, signature
)
);
}
template <class Class, class Options>
void visit(Class& cl, char const* name, Options const& options) const
{
this->visit_aux(
cl, name, options
, boost::python::detail::get_signature(fn, (typename Class::wrapped_type*)0)
);
}
F fn;
};
// Member function adaptor that releases and aqcuires the GIL
// around the function call.
template <class F>
visitor<F> allow_threads(F fn)
{
return visitor<F>(fn);
}
//}} // namespace libtorrent::python
#endif // GIL_070107_HPP

View file

@ -0,0 +1,48 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/module.hpp>
void bind_utility();
void bind_fingerprint();
void bind_big_number();
void bind_session();
void bind_entry();
void bind_torrent_info();
void bind_filesystem();
void bind_torrent_handle();
void bind_torrent_status();
void bind_session_settings();
void bind_version();
void bind_alert();
void bind_datetime();
void bind_extensions();
void bind_peer_plugin();
void bind_torrent();
void bind_peer_info();
BOOST_PYTHON_MODULE(libtorrent)
{
Py_Initialize();
PyEval_InitThreads();
bind_utility();
bind_fingerprint();
bind_big_number();
bind_entry();
bind_session();
bind_torrent_info();
bind_filesystem();
bind_torrent_handle();
bind_torrent_status();
bind_session_settings();
bind_version();
bind_alert();
bind_datetime();
bind_extensions();
bind_peer_plugin();
bind_torrent();
bind_peer_info();
}

View file

@ -0,0 +1,31 @@
// Copyright Daniel Wallin 2007. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef OPTIONAL_070108_HPP
# define OPTIONAL_070108_HPP
# include <boost/python.hpp>
# include <boost/optional.hpp>
template <class T>
struct optional_to_python
{
optional_to_python()
{
boost::python::to_python_converter<
boost::optional<T>, optional_to_python<T>
>();
}
static PyObject* convert(boost::optional<T> const& x)
{
if (!x)
return boost::python::incref(Py_None);
return boost::python::incref(boost::python::object(*x).ptr());
}
};
#endif // OPTIONAL_070108_HPP

View file

@ -0,0 +1,63 @@
// Copyright Daniel Wallin 2007. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/peer_info.hpp>
#include <boost/python.hpp>
using namespace boost::python;
using namespace libtorrent;
void bind_peer_info()
{
scope pi = class_<peer_info>("peer_info")
.def_readonly("flags", &peer_info::flags)
.def_readonly("ip", &peer_info::ip)
.def_readonly("up_speed", &peer_info::up_speed)
.def_readonly("down_speed", &peer_info::down_speed)
.def_readonly("payload_up_speed", &peer_info::payload_up_speed)
.def_readonly("payload_down_speed", &peer_info::payload_down_speed)
.def_readonly("total_download", &peer_info::total_download)
.def_readonly("total_upload", &peer_info::total_upload)
.def_readonly("pid", &peer_info::pid)
.def_readonly("pieces", &peer_info::pieces)
.def_readonly("upload_limit", &peer_info::upload_limit)
.def_readonly("download_limit", &peer_info::download_limit)
.def_readonly("load_balancing", &peer_info::load_balancing)
.def_readonly("download_queue_length", &peer_info::download_queue_length)
.def_readonly("upload_queue_length", &peer_info::upload_queue_length)
.def_readonly("downloading_piece_index", &peer_info::downloading_piece_index)
.def_readonly("downloading_block_index", &peer_info::downloading_block_index)
.def_readonly("downloading_progress", &peer_info::downloading_progress)
.def_readonly("downloading_total", &peer_info::downloading_total)
.def_readonly("client", &peer_info::client)
.def_readonly("connection_type", &peer_info::connection_type)
.def_readonly("source", &peer_info::source)
;
pi.attr("interesting") = (int)peer_info::interesting;
pi.attr("choked") = (int)peer_info::choked;
pi.attr("remote_interested") = (int)peer_info::remote_interested;
pi.attr("remote_choked") = (int)peer_info::remote_choked;
pi.attr("supports_extensions") = (int)peer_info::supports_extensions;
pi.attr("local_connection") = (int)peer_info::local_connection;
pi.attr("handshake") = (int)peer_info::handshake;
pi.attr("connecting") = (int)peer_info::connecting;
pi.attr("queued") = (int)peer_info::queued;
pi.attr("on_parole") = (int)peer_info::on_parole;
pi.attr("seed") = (int)peer_info::seed;
#ifndef TORRENT_DISABLE_ENCRYPTION
pi.attr("rc4_encrypted") = (int)peer_info::rc4_encrypted;
pi.attr("plaintext_encrypted") = (int)peer_info::plaintext_encrypted;
#endif
pi.attr("standard_bittorrent") = 0;
pi.attr("web_seed") = 1;
pi.attr("tracker") = 0x1;
pi.attr("dht") = 0x2;
pi.attr("pex") = 0x4;
pi.attr("lsd") = 0x8;
pi.attr("resume_data") = 0x10;
}

View file

@ -0,0 +1,344 @@
// Copyright Daniel Wallin 2007. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/extensions.hpp>
#include <libtorrent/entry.hpp>
#include <libtorrent/peer_request.hpp>
#include <boost/python.hpp>
using namespace boost::python;
using namespace libtorrent;
namespace
{
struct peer_plugin_wrap : peer_plugin, wrapper<peer_plugin>
{
void add_handshake(entry& e)
{
if (override f = this->get_override("add_handshake"))
e = call<entry>(f.ptr(), e);
else
peer_plugin::add_handshake(e);
}
void default_add_handshake(entry& e)
{
this->peer_plugin::add_handshake(e);
}
bool on_handshake()
{
if (override f = this->get_override("on_handshake"))
return f();
else
return peer_plugin::on_handshake();
}
bool default_on_handshake()
{
return this->peer_plugin::on_handshake();
}
bool on_extension_handshake(entry const& e)
{
if (override f = this->get_override("on_extension_handshake"))
return f(e);
else
return peer_plugin::on_extension_handshake(e);
}
bool default_on_extension_handshake(entry const& e)
{
return this->peer_plugin::on_extension_handshake(e);
}
bool on_choke()
{
if (override f = this->get_override("on_choke"))
return f();
else
return peer_plugin::on_choke();
}
bool default_on_choke()
{
return this->peer_plugin::on_choke();
}
bool on_unchoke()
{
if (override f = this->get_override("on_unchoke"))
return f();
else
return peer_plugin::on_unchoke();
}
bool default_on_unchoke()
{
return this->peer_plugin::on_unchoke();
}
bool on_interested()
{
if (override f = this->get_override("on_interested"))
return f();
else
return peer_plugin::on_interested();
}
bool default_on_interested()
{
return this->peer_plugin::on_interested();
}
bool on_not_interested()
{
if (override f = this->get_override("on_not_interested"))
return f();
else
return peer_plugin::on_not_interested();
}
bool default_on_not_interested()
{
return this->peer_plugin::on_not_interested();
}
bool on_have(int index)
{
if (override f = this->get_override("on_have"))
return f(index);
else
return peer_plugin::on_have(index);
}
bool default_on_have(int index)
{
return this->peer_plugin::on_have(index);
}
bool on_bitfield(std::vector<bool> const& bitfield)
{
if (override f = this->get_override("on_bitfield"))
return f(bitfield);
else
return peer_plugin::on_bitfield(bitfield);
}
bool default_on_bitfield(std::vector<bool> const& bitfield)
{
return this->peer_plugin::on_bitfield(bitfield);
}
bool on_request(peer_request const& req)
{
if (override f = this->get_override("on_request"))
return f(req);
else
return peer_plugin::on_request(req);
}
bool default_on_request(peer_request const& req)
{
return this->peer_plugin::on_request(req);
}
bool on_piece(peer_request const& piece, char const* data)
{
if (override f = this->get_override("on_piece"))
return f(piece, data);
else
return peer_plugin::on_piece(piece, data);
}
bool default_on_piece(peer_request const& piece, char const* data)
{
return this->peer_plugin::on_piece(piece, data);
}
bool on_cancel(peer_request const& req)
{
if (override f = this->get_override("on_cancel"))
return f(req);
else
return peer_plugin::on_cancel(req);
}
bool default_on_cancel(peer_request const& req)
{
return this->peer_plugin::on_cancel(req);
}
bool on_extended(int length, int msg, buffer::const_interval body)
{
if (override f = this->get_override("on_extended"))
return f(length, msg, body);
else
return peer_plugin::on_extended(length, msg, body);
}
bool default_on_extended(int length, int msg, buffer::const_interval body)
{
return this->peer_plugin::on_extended(length, msg, body);
}
bool on_unknown_message(int length, int msg, buffer::const_interval body)
{
if (override f = this->get_override("on_unknown_message"))
return f(length, msg, body);
else
return peer_plugin::on_unknown_message(length, msg, body);
}
bool default_on_unknown_message(int length, int msg, buffer::const_interval body)
{
return this->peer_plugin::on_unknown_message(length, msg, body);
}
void on_piece_pass(int index)
{
if (override f = this->get_override("on_piece_pass"))
f(index);
else
peer_plugin::on_piece_pass(index);
}
void default_on_piece_pass(int index)
{
this->peer_plugin::on_piece_pass(index);
}
void on_piece_failed(int index)
{
if (override f = this->get_override("on_piece_failed"))
f(index);
else
peer_plugin::on_piece_failed(index);
}
void default_on_piece_failed(int index)
{
this->peer_plugin::on_piece_failed(index);
}
void tick()
{
if (override f = this->get_override("tick"))
f();
else
peer_plugin::tick();
}
void default_tick()
{
this->peer_plugin::tick();
}
bool write_request(peer_request const& req)
{
if (override f = this->get_override("write_request"))
return f(req);
else
return peer_plugin::write_request(req);
}
bool default_write_request(peer_request const& req)
{
return this->peer_plugin::write_request(req);
}
};
object get_buffer()
{
static char const data[] = "foobar";
return object(handle<>(PyBuffer_FromMemory((void*)data, 6)));
}
} // namespace unnamed
void bind_peer_plugin()
{
class_<
peer_plugin_wrap, boost::shared_ptr<peer_plugin_wrap>, boost::noncopyable
>("peer_plugin")
.def(
"add_handshake"
, &peer_plugin::add_handshake, &peer_plugin_wrap::default_add_handshake
)
.def(
"on_handshake"
, &peer_plugin::on_handshake, &peer_plugin_wrap::default_on_handshake
)
.def(
"on_extension_handshake"
, &peer_plugin::on_extension_handshake
, &peer_plugin_wrap::default_on_extension_handshake
)
.def(
"on_choke"
, &peer_plugin::on_choke, &peer_plugin_wrap::default_on_choke
)
.def(
"on_unchoke"
, &peer_plugin::on_unchoke, &peer_plugin_wrap::default_on_unchoke
)
.def(
"on_interested"
, &peer_plugin::on_interested, &peer_plugin_wrap::default_on_interested
)
.def(
"on_not_interested"
, &peer_plugin::on_not_interested, &peer_plugin_wrap::default_on_not_interested
)
.def(
"on_have"
, &peer_plugin::on_have, &peer_plugin_wrap::default_on_have
)
.def(
"on_bitfield"
, &peer_plugin::on_bitfield, &peer_plugin_wrap::default_on_bitfield
)
.def(
"on_request"
, &peer_plugin::on_request, &peer_plugin_wrap::default_on_request
)
.def(
"on_piece"
, &peer_plugin::on_piece, &peer_plugin_wrap::default_on_piece
)
.def(
"on_cancel"
, &peer_plugin::on_cancel, &peer_plugin_wrap::default_on_cancel
)
.def(
"on_piece_pass"
, &peer_plugin::on_piece_pass, &peer_plugin_wrap::default_on_piece_pass
)
.def(
"on_piece_failed"
, &peer_plugin::on_piece_failed, &peer_plugin_wrap::default_on_piece_failed
)
.def(
"tick"
, &peer_plugin::tick, &peer_plugin_wrap::default_tick
)
.def(
"write_request"
, &peer_plugin::write_request, &peer_plugin_wrap::default_write_request
)
// These seem to make VC7.1 freeze. Needs special handling.
/*.def(
"on_extended"
, &peer_plugin::on_extended, &peer_plugin_wrap::default_on_extended
)
.def(
"on_unknown_message"
, &peer_plugin::on_unknown_message, &peer_plugin_wrap::default_on_unknown_message
)*/
;
def("get_buffer", &get_buffer);
}

View file

@ -0,0 +1,214 @@
// Copyright Daniel Wallin, Arvid Norberg 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/session.hpp>
#include <libtorrent/torrent.hpp>
#include <libtorrent/storage.hpp>
#include <boost/python.hpp>
#include "gil.hpp"
using namespace boost::python;
using namespace libtorrent;
extern char const* session_status_doc;
extern char const* session_status_has_incoming_connections_doc;
extern char const* session_status_upload_rate_doc;
extern char const* session_status_download_rate_doc;
extern char const* session_status_payload_upload_rate_doc;
extern char const* session_status_payload_download_rate_doc;
extern char const* session_status_total_download_doc;
extern char const* session_status_total_upload_doc;
extern char const* session_status_total_payload_download_doc;
extern char const* session_status_total_payload_upload_doc;
extern char const* session_status_num_peers_doc;
extern char const* session_status_dht_nodes_doc;
extern char const* session_status_cache_nodes_doc;
extern char const* session_status_dht_torrents_doc;
extern char const* session_doc;
extern char const* session_init_doc;
extern char const* session_listen_on_doc;
extern char const* session_is_listening_doc;
extern char const* session_listen_port_doc;
extern char const* session_status_m_doc;
extern char const* session_start_dht_doc;
extern char const* session_stop_dht_doc;
extern char const* session_dht_state_doc;
extern char const* session_add_torrent_doc;
extern char const* session_remove_torrent_doc;
extern char const* session_set_download_rate_limit_doc;
extern char const* session_set_upload_rate_limit_doc;
extern char const* session_set_max_uploads_doc;
extern char const* session_set_max_connections_doc;
extern char const* session_set_max_half_open_connections_doc;
extern char const* session_set_settings_doc;
extern char const* session_set_severity_level_doc;
extern char const* session_pop_alert_doc;
namespace
{
bool listen_on(session& s, int min_, int max_, char const* interface)
{
allow_threading_guard guard;
return s.listen_on(std::make_pair(min_, max_), interface);
}
struct invoke_extension_factory
{
invoke_extension_factory(object const& callback)
: cb(callback)
{}
boost::shared_ptr<torrent_plugin> operator()(torrent* t)
{
lock_gil lock;
return extract<boost::shared_ptr<torrent_plugin> >(cb(ptr(t)))();
}
object cb;
};
void add_extension(session& s, object const& e)
{
allow_threading_guard guard;
s.add_extension(invoke_extension_factory(e));
}
torrent_handle add_torrent(session& s, torrent_info const& ti
, boost::filesystem::path const& save, entry const& resume
, bool compact, int block_size)
{
allow_threading_guard guard;
return s.add_torrent(ti, save, resume, compact, block_size
, default_storage_constructor);
}
} // namespace unnamed
void bind_session()
{
class_<session_status>("session_status", session_status_doc)
.def_readonly(
"has_incoming_connections", &session_status::has_incoming_connections
, session_status_has_incoming_connections_doc
)
.def_readonly(
"upload_rate", &session_status::upload_rate
, session_status_upload_rate_doc
)
.def_readonly(
"download_rate", &session_status::download_rate
, session_status_download_rate_doc
)
.def_readonly(
"payload_upload_rate", &session_status::payload_upload_rate
, session_status_payload_upload_rate_doc
)
.def_readonly(
"payload_download_rate", &session_status::payload_download_rate
, session_status_payload_download_rate_doc
)
.def_readonly(
"total_download", &session_status::total_download
, session_status_total_download_doc
)
.def_readonly(
"total_upload", &session_status::total_upload
, session_status_total_upload_doc
)
.def_readonly(
"total_payload_download", &session_status::total_payload_download
, session_status_total_payload_download_doc
)
.def_readonly(
"total_payload_upload", &session_status::total_payload_upload
, session_status_total_payload_upload_doc
)
.def_readonly(
"num_peers", &session_status::num_peers
, session_status_num_peers_doc
)
#ifndef TORRENT_DISABLE_DHT
.def_readonly(
"dht_nodes", &session_status::dht_nodes
, session_status_dht_nodes_doc
)
.def_readonly(
"dht_cache_nodes", &session_status::dht_node_cache
, session_status_cache_nodes_doc
)
.def_readonly(
"dht_torrents", &session_status::dht_torrents
, session_status_dht_torrents_doc
)
#endif
;
class_<session, boost::noncopyable>("session", session_doc, no_init)
.def(
init<fingerprint>(arg("fingerprint")=fingerprint("LT",0,1,0,0), session_init_doc)
)
.def(
"listen_on", &listen_on
, (arg("min"), "max", arg("interface") = (char const*)0)
, session_listen_on_doc
)
.def("is_listening", allow_threads(&session::is_listening), session_is_listening_doc)
.def("listen_port", allow_threads(&session::listen_port), session_listen_port_doc)
.def("status", allow_threads(&session::status), session_status_m_doc)
#ifndef TORRENT_DISABLE_DHT
.def("start_dht", allow_threads(&session::start_dht), session_start_dht_doc)
.def("stop_dht", allow_threads(&session::stop_dht), session_stop_dht_doc)
.def("dht_state", allow_threads(&session::dht_state), session_dht_state_doc)
#endif
.def(
"add_torrent", &add_torrent
, (
arg("torrent_info"), "save_path", arg("resume_data") = entry()
, arg("compact_mode") = true, arg("block_size") = 16 * 1024
)
, session_add_torrent_doc
)
.def("remove_torrent", allow_threads(&session::remove_torrent), session_remove_torrent_doc)
.def(
"set_download_rate_limit", allow_threads(&session::set_download_rate_limit)
, session_set_download_rate_limit_doc
)
.def(
"set_upload_rate_limit", allow_threads(&session::set_upload_rate_limit)
, session_set_upload_rate_limit_doc
)
.def(
"set_max_uploads", allow_threads(&session::set_max_uploads)
, session_set_max_uploads_doc
)
.def(
"set_max_connections", allow_threads(&session::set_max_connections)
, session_set_max_connections_doc
)
.def(
"set_max_half_open_connections", allow_threads(&session::set_max_half_open_connections)
, session_set_max_half_open_connections_doc
)
.def("set_settings", allow_threads(&session::set_settings), session_set_settings_doc)
.def(
"set_severity_level", allow_threads(&session::set_severity_level)
, session_set_severity_level_doc
)
.def("pop_alert", allow_threads(&session::pop_alert), session_pop_alert_doc)
.def("add_extension", &add_extension)
.def("set_peer_proxy", allow_threads(&session::set_peer_proxy))
.def("set_tracker_proxy", allow_threads(&session::set_tracker_proxy))
.def("set_web_seed_proxy", allow_threads(&session::set_web_seed_proxy))
#ifndef TORRENT_DISABLE_DHT
.def("set_dht_proxy", allow_threads(&session::set_dht_proxy))
#endif
;
def("supports_sparse_files", &supports_sparse_files);
register_ptr_to_python<std::auto_ptr<alert> >();
}

View file

@ -0,0 +1,77 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/session.hpp>
#include <boost/python.hpp>
using namespace boost::python;
using namespace libtorrent;
void bind_session_settings()
{
class_<session_settings>("session_settings")
.def_readwrite("user_agent", &session_settings::user_agent)
.def_readwrite("tracker_completion_timeout", &session_settings::tracker_completion_timeout)
.def_readwrite("tracker_receive_timeout", &session_settings::tracker_receive_timeout)
.def_readwrite("tracker_maximum_response_length", &session_settings::tracker_maximum_response_length)
.def_readwrite("piece_timeout", &session_settings::piece_timeout)
.def_readwrite("request_queue_time", &session_settings::request_queue_time)
.def_readwrite("max_allowed_in_request_queue", &session_settings::max_allowed_in_request_queue)
.def_readwrite("max_out_request_queue", &session_settings::max_out_request_queue)
.def_readwrite("whole_pieces_threshold", &session_settings::whole_pieces_threshold)
.def_readwrite("peer_timeout", &session_settings::peer_timeout)
.def_readwrite("urlseed_timeout", &session_settings::urlseed_timeout)
.def_readwrite("urlseed_pipeline_size", &session_settings::urlseed_pipeline_size)
.def_readwrite("file_pool_size", &session_settings::file_pool_size)
.def_readwrite("allow_multiple_connections_per_ip", &session_settings::allow_multiple_connections_per_ip)
.def_readwrite("max_failcount", &session_settings::max_failcount)
.def_readwrite("min_reconnect_time", &session_settings::min_reconnect_time)
.def_readwrite("peer_connect_timeout", &session_settings::peer_connect_timeout)
.def_readwrite("ignore_limits_on_local_network", &session_settings::ignore_limits_on_local_network)
.def_readwrite("connection_speed", &session_settings::connection_speed)
.def_readwrite("send_redundant_have", &session_settings::send_redundant_have)
.def_readwrite("lazy_bitfields", &session_settings::lazy_bitfields)
.def_readwrite("inactivity_timeout", &session_settings::inactivity_timeout)
.def_readwrite("unchoke_interval", &session_settings::unchoke_interval)
#ifndef TORRENT_DISABLE_DHT
.def_readwrite("use_dht_as_fallback", &session_settings::use_dht_as_fallback)
#endif
;
enum_<proxy_settings::proxy_type>("proxy_type")
.value("none", proxy_settings::none)
.value("socks4", proxy_settings::socks4)
.value("socks5", proxy_settings::socks5)
.value("socks5_pw", proxy_settings::socks5_pw)
.value("http", proxy_settings::http)
.value("http_pw", proxy_settings::http_pw)
;
scope ps = class_<proxy_settings>("proxy_settings")
.def_readwrite("hostname", &proxy_settings::hostname)
.def_readwrite("port", &proxy_settings::port)
.def_readwrite("password", &proxy_settings::password)
.def_readwrite("username", &proxy_settings::username)
.def_readwrite("type", &proxy_settings::type)
;
enum_<pe_settings::enc_policy>("enc_policy")
.value("forced", pe_settings::forced)
.value("enabled", pe_settings::enabled)
.value("disabled", pe_settings::disabled)
;
enum_<pe_settings::enc_level>("enc_level")
.value("rc4", pe_settings::rc4)
.value("plaintext", pe_settings::plaintext)
;
scope pes = class_<pe_settings>("pe_settings")
.def_readwrite("out_enc_policy", &pe_settings::out_enc_policy)
.def_readwrite("in_enc_policy", &pe_settings::in_enc_policy)
.def_readwrite("allowed_enc_level", &pe_settings::allowed_enc_level)
.def_readwrite("prefer_rc4", &pe_settings::prefer_rc4)
;
}

View file

@ -0,0 +1,15 @@
// Copyright Daniel Wallin 2007. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/torrent.hpp>
#include <boost/python.hpp>
using namespace boost::python;
using namespace libtorrent;
void bind_torrent()
{
class_<torrent, boost::noncopyable>("torrent", no_init);
}

View file

@ -0,0 +1,163 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/torrent_handle.hpp>
#include <boost/python.hpp>
#include "gil.hpp"
using namespace boost::python;
using namespace libtorrent;
namespace
{
std::vector<announce_entry>::const_iterator begin_trackers(torrent_handle& i)
{
allow_threading_guard guard;
return i.trackers().begin();
}
std::vector<announce_entry>::const_iterator end_trackers(torrent_handle& i)
{
allow_threading_guard guard;
return i.trackers().end();
}
} // namespace unnamed
list file_progress(torrent_handle& handle)
{
std::vector<float> p;
{
allow_threading_guard guard;
p.reserve(handle.get_torrent_info().num_files());
handle.file_progress(p);
}
list result;
for (std::vector<float>::iterator i(p.begin()), e(p.end()); i != e; ++i)
result.append(*i);
return result;
}
list get_peer_info(torrent_handle const& handle)
{
std::vector<peer_info> pi;
{
allow_threading_guard guard;
handle.get_peer_info(pi);
}
list result;
for (std::vector<peer_info>::iterator i = pi.begin(); i != pi.end(); ++i)
{
result.append(*i);
}
return result;
}
void replace_trackers(torrent_handle& info, object trackers)
{
object iter(trackers.attr("__iter__")());
std::vector<announce_entry> result;
for (;;)
{
handle<> entry(allow_null(PyIter_Next(iter.ptr())));
if (entry == handle<>())
break;
result.push_back(extract<announce_entry const&>(object(entry)));
}
allow_threading_guard guard;
info.replace_trackers(result);
}
list get_download_queue(torrent_handle& handle)
{
list ret;
std::vector<partial_piece_info> downloading;
{
allow_threading_guard guard;
handle.get_download_queue(downloading);
}
for (std::vector<partial_piece_info>::iterator i = downloading.begin()
, end(downloading.end()); i != end; ++i)
{
dict partial_piece;
partial_piece["piece_index"] = i->piece_index;
partial_piece["blocks_in_piece"] = i->blocks_in_piece;
list block_list;
for (int k = 0; k < i->blocks_in_piece; ++k)
{
dict block_info;
block_info["state"] = i->blocks[k].state;
block_info["num_downloads"] = i->blocks[k].num_downloads;
// block_info["peer"] = i->info[k].peer;
block_list.append(block_info);
}
partial_piece["blocks"] = block_list;
ret.append(partial_piece);
}
return ret;
}
void bind_torrent_handle()
{
void (torrent_handle::*force_reannounce0)() const = &torrent_handle::force_reannounce;
void (torrent_handle::*force_reannounce1)(boost::posix_time::time_duration) const
= &torrent_handle::force_reannounce;
return_value_policy<copy_const_reference> copy;
#define _ allow_threads
class_<torrent_handle>("torrent_handle")
.def("status", _(&torrent_handle::status))
.def("torrent_info", _(&torrent_handle::get_torrent_info), return_internal_reference<>())
.def("is_valid", _(&torrent_handle::is_valid))
.def("write_resume_data", _(&torrent_handle::write_resume_data))
.def("force_reannounce", _(force_reannounce0))
.def("force_reannounce", _(force_reannounce1))
.def("set_tracker_login", _(&torrent_handle::set_tracker_login))
.def("add_url_seed", _(&torrent_handle::add_url_seed))
.def("set_ratio", _(&torrent_handle::set_ratio))
.def("set_max_uploads", _(&torrent_handle::set_max_uploads))
.def("set_max_connections", _(&torrent_handle::set_max_connections))
.def("set_upload_limit", _(&torrent_handle::set_upload_limit))
.def("set_download_limit", _(&torrent_handle::set_download_limit))
.def("set_sequenced_download_threshold", _(&torrent_handle::set_sequenced_download_threshold))
.def("pause", _(&torrent_handle::pause))
.def("resume", _(&torrent_handle::resume))
.def("is_paused", _(&torrent_handle::is_paused))
.def("is_seed", _(&torrent_handle::is_seed))
.def("filter_piece", _(&torrent_handle::filter_piece))
.def("is_piece_filtered", _(&torrent_handle::is_piece_filtered))
.def("has_metadata", _(&torrent_handle::has_metadata))
.def("save_path", _(&torrent_handle::save_path))
.def("move_storage", _(&torrent_handle::move_storage))
.def("info_hash", _(&torrent_handle::info_hash), copy)
.def("file_progress", file_progress)
.def("trackers", range(begin_trackers, end_trackers))
.def("replace_trackers", replace_trackers)
.def("get_peer_info", get_peer_info)
.def("get_download_queue", get_download_queue)
;
}

View file

@ -0,0 +1,103 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include <libtorrent/torrent_info.hpp>
using namespace boost::python;
using namespace libtorrent;
namespace
{
std::vector<announce_entry>::const_iterator begin_trackers(torrent_info& i)
{
return i.trackers().begin();
}
std::vector<announce_entry>::const_iterator end_trackers(torrent_info& i)
{
return i.trackers().end();
}
void add_node(torrent_info& ti, char const* hostname, int port)
{
ti.add_node(std::make_pair(hostname, port));
}
list nodes(torrent_info const& ti)
{
list result;
typedef std::vector<std::pair<std::string, int> > list_type;
for (list_type::const_iterator i = ti.nodes().begin(); i != ti.nodes().end(); ++i)
{
result.append(make_tuple(i->first, i->second));
}
return result;
}
} // namespace unnamed
void bind_torrent_info()
{
return_value_policy<copy_const_reference> copy;
class_<torrent_info>("torrent_info")
.def(init<entry const&>())
.def(init<sha1_hash const&>())
.def("create_torrent", &torrent_info::create_torrent)
.def("set_comment", &torrent_info::set_comment)
.def("set_piece_size", &torrent_info::set_piece_size)
.def("set_creator", &torrent_info::set_creator)
.def("set_hash", &torrent_info::set_hash)
.def("add_tracker", &torrent_info::add_tracker, (arg("url"), arg("tier")=0))
.def("add_file", &torrent_info::add_file)
.def("add_url_seed", &torrent_info::add_url_seed)
.def("name", &torrent_info::name, copy)
.def("comment", &torrent_info::comment, copy)
.def("creator", &torrent_info::creator, copy)
.def("total_size", &torrent_info::total_size)
.def("piece_length", &torrent_info::piece_length)
.def("num_pieces", &torrent_info::num_pieces)
.def("info_hash", &torrent_info::info_hash, copy)
.def("hash_for_piece", &torrent_info::hash_for_piece, copy)
.def("piece_size", &torrent_info::piece_size)
.def("file_at", &torrent_info::file_at, return_internal_reference<>())
.def("files", range(&torrent_info::begin_files, &torrent_info::end_files))
.def("priv", &torrent_info::priv)
.def("set_priv", &torrent_info::set_priv)
.def("trackers", range(begin_trackers, end_trackers))
.def("creation_date", &torrent_info::creation_date)
.def("add_node", &add_node)
.def("nodes", &nodes)
;
class_<file_entry>("file_entry")
.add_property(
"path"
, make_getter(
&file_entry::path, return_value_policy<copy_non_const_reference>()
)
)
.def_readonly("offset", &file_entry::offset)
.def_readonly("size", &file_entry::size)
;
class_<announce_entry>("announce_entry", init<std::string const&>())
.def_readwrite("url", &announce_entry::url)
.def_readwrite("tier", &announce_entry::tier)
;
}

View file

@ -0,0 +1,107 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/torrent_handle.hpp>
#include <boost/python.hpp>
using namespace boost::python;
using namespace libtorrent;
object pieces(torrent_status const& s)
{
list result;
for (std::vector<bool>::const_iterator i(s.pieces->begin()), e(s.pieces->end()); i != e; ++i)
result.append(*i);
return result;
}
extern char const* torrent_status_doc;
extern char const* torrent_status_state_doc;
extern char const* torrent_status_paused_doc;
extern char const* torrent_status_progress_doc;
extern char const* torrent_status_next_announce_doc;
extern char const* torrent_status_announce_interval_doc;
extern char const* torrent_status_current_tracker_doc;
extern char const* torrent_status_total_download_doc;
extern char const* torrent_status_total_upload_doc;
extern char const* torrent_status_total_payload_download_doc;
extern char const* torrent_status_total_payload_upload_doc;
extern char const* torrent_status_total_failed_bytes_doc;
void bind_torrent_status()
{
scope status = class_<torrent_status>("torrent_status", torrent_status_doc)
.def_readonly("state", &torrent_status::state, torrent_status_state_doc)
.def_readonly("paused", &torrent_status::paused, torrent_status_paused_doc)
.def_readonly("progress", &torrent_status::progress, torrent_status_progress_doc)
.add_property(
"next_announce"
, make_getter(
&torrent_status::next_announce, return_value_policy<return_by_value>()
)
, torrent_status_next_announce_doc
)
.add_property(
"announce_interval"
, make_getter(
&torrent_status::announce_interval, return_value_policy<return_by_value>()
)
, torrent_status_announce_interval_doc
)
.def_readonly(
"current_tracker", &torrent_status::current_tracker
, torrent_status_current_tracker_doc
)
.def_readonly(
"total_download", &torrent_status::total_download
, torrent_status_total_download_doc
)
.def_readonly(
"total_upload", &torrent_status::total_upload
, torrent_status_total_upload_doc
)
.def_readonly(
"total_payload_download", &torrent_status::total_payload_download
, torrent_status_total_payload_download_doc
)
.def_readonly(
"total_payload_upload", &torrent_status::total_payload_upload
, torrent_status_total_payload_upload_doc
)
.def_readonly(
"total_failed_bytes", &torrent_status::total_failed_bytes
, torrent_status_total_failed_bytes_doc
)
.def_readonly("total_redundant_bytes", &torrent_status::total_redundant_bytes)
.def_readonly("download_rate", &torrent_status::download_rate)
.def_readonly("upload_rate", &torrent_status::upload_rate)
.def_readonly("download_payload_rate", &torrent_status::download_payload_rate)
.def_readonly("upload_payload_rate", &torrent_status::upload_payload_rate)
.def_readonly("num_peers", &torrent_status::num_peers)
.def_readonly("num_complete", &torrent_status::num_complete)
.def_readonly("num_incomplete", &torrent_status::num_incomplete)
.add_property("pieces", pieces)
.def_readonly("num_pieces", &torrent_status::num_pieces)
.def_readonly("total_done", &torrent_status::total_done)
.def_readonly("total_wanted_done", &torrent_status::total_wanted_done)
.def_readonly("total_wanted", &torrent_status::total_wanted)
.def_readonly("num_seeds", &torrent_status::num_seeds)
.def_readonly("distributed_copies", &torrent_status::distributed_copies)
.def_readonly("block_size", &torrent_status::block_size)
;
enum_<torrent_status::state_t>("states")
.value("queued_for_checking", torrent_status::queued_for_checking)
.value("checking_files", torrent_status::checking_files)
.value("connecting_to_tracker", torrent_status::connecting_to_tracker)
.value("downloading", torrent_status::downloading)
.value("finished", torrent_status::finished)
.value("seeding", torrent_status::seeding)
.value("allocating", torrent_status::allocating)
.export_values()
;
}

View file

@ -0,0 +1,37 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/identify_client.hpp>
#include <libtorrent/bencode.hpp>
#include <boost/python.hpp>
using namespace boost::python;
using namespace libtorrent;
object client_fingerprint_(peer_id const& id)
{
boost::optional<fingerprint> result = client_fingerprint(id);
return result ? object(*result) : object();
}
entry bdecode_(std::string const& data)
{
return bdecode(data.begin(), data.end());
}
std::string bencode_(entry const& e)
{
std::string result;
bencode(std::back_inserter(result), e);
return result;
}
void bind_utility()
{
def("identify_client", &libtorrent::identify_client);
def("client_fingerprint", &client_fingerprint_);
def("bdecode", &bdecode_);
def("bencode", &bencode_);
}

View file

@ -0,0 +1,16 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/version.hpp>
#include <boost/python.hpp>
using namespace boost::python;
void bind_version()
{
scope().attr("version") = LIBTORRENT_VERSION;
scope().attr("version_major") = LIBTORRENT_VERSION_MAJOR;
scope().attr("version_minor") = LIBTORRENT_VERSION_MINOR;
}

View file

@ -0,0 +1,232 @@
nobase_include_HEADERS = libtorrent/alert.hpp \
libtorrent/alert_types.hpp \
libtorrent/allocate_resources.hpp \
libtorrent/bandwidth_manager.hpp \
libtorrent/bencode.hpp \
libtorrent/buffer.hpp \
libtorrent/connection_queue.hpp \
libtorrent/config.hpp \
libtorrent/debug.hpp \
libtorrent/disk_io_thread.hpp \
libtorrent/entry.hpp \
libtorrent/escape_string.hpp \
libtorrent/extensions.hpp \
libtorrent/file.hpp \
libtorrent/file_pool.hpp \
libtorrent/fingerprint.hpp \
libtorrent/hasher.hpp \
libtorrent/http_connection.hpp \
libtorrent/http_stream.hpp \
libtorrent/http_tracker_connection.hpp \
libtorrent/identify_client.hpp \
libtorrent/instantiate_connection.hpp \
libtorrent/intrusive_ptr_base.hpp \
libtorrent/invariant_check.hpp \
libtorrent/io.hpp \
libtorrent/ip_filter.hpp \
libtorrent/lsd.hpp \
libtorrent/peer.hpp \
libtorrent/peer_connection.hpp \
libtorrent/bt_peer_connection.hpp \
libtorrent/web_peer_connection.hpp \
libtorrent/pe_crypto.hpp \
libtorrent/natpmp.hpp \
libtorrent/pch.hpp \
libtorrent/peer_id.hpp \
libtorrent/peer_info.hpp \
libtorrent/peer_request.hpp \
libtorrent/piece_block_progress.hpp \
libtorrent/piece_picker.hpp \
libtorrent/policy.hpp \
libtorrent/proxy_base.hpp \
libtorrent/random_sample.hpp \
libtorrent/resource_request.hpp \
libtorrent/session.hpp \
libtorrent/session_settings.hpp \
libtorrent/session_status.hpp \
libtorrent/size_type.hpp \
libtorrent/socket.hpp \
libtorrent/socket_type.hpp \
libtorrent/socks4_stream.hpp \
libtorrent/socks5_stream.hpp \
libtorrent/stat.hpp \
libtorrent/storage.hpp \
libtorrent/time.hpp \
libtorrent/torrent.hpp \
libtorrent/torrent_handle.hpp \
libtorrent/torrent_info.hpp \
libtorrent/tracker_manager.hpp \
libtorrent/udp_tracker_connection.hpp \
libtorrent/utf8.hpp \
libtorrent/xml_parse.hpp \
libtorrent/variant_stream.hpp \
libtorrent/version.hpp \
libtorrent/time.hpp \
libtorrent/aux_/allocate_resources_impl.hpp \
libtorrent/aux_/session_impl.hpp \
libtorrent/extensions/metadata_transfer.hpp \
libtorrent/extensions/ut_pex.hpp \
libtorrent/extensions/logger.hpp \
\
libtorrent/kademlia/closest_nodes.hpp \
libtorrent/kademlia/dht_tracker.hpp \
libtorrent/kademlia/find_data.hpp \
libtorrent/kademlia/logging.hpp \
libtorrent/kademlia/msg.hpp \
libtorrent/kademlia/node.hpp \
libtorrent/kademlia/node_entry.hpp \
libtorrent/kademlia/node_id.hpp \
libtorrent/kademlia/observer.hpp \
libtorrent/kademlia/packet_iterator.hpp \
libtorrent/kademlia/refresh.hpp \
libtorrent/kademlia/routing_table.hpp \
libtorrent/kademlia/rpc_manager.hpp \
libtorrent/kademlia/traversal_algorithm.hpp \
\
libtorrent/asio.hpp \
libtorrent/asio/basic_datagram_socket.hpp \
libtorrent/asio/basic_deadline_timer.hpp \
libtorrent/asio/basic_io_object.hpp \
libtorrent/asio/basic_socket.hpp \
libtorrent/asio/basic_socket_acceptor.hpp \
libtorrent/asio/basic_socket_iostream.hpp \
libtorrent/asio/basic_socket_streambuf.hpp \
libtorrent/asio/basic_stream_socket.hpp \
libtorrent/asio/basic_streambuf.hpp \
libtorrent/asio/buffer.hpp \
libtorrent/asio/buffered_read_stream.hpp \
libtorrent/asio/buffered_read_stream_fwd.hpp \
libtorrent/asio/buffered_stream.hpp \
libtorrent/asio/buffered_stream_fwd.hpp \
libtorrent/asio/buffered_write_stream.hpp \
libtorrent/asio/buffered_write_stream_fwd.hpp \
libtorrent/asio/completion_condition.hpp \
libtorrent/asio/datagram_socket_service.hpp \
libtorrent/asio/deadline_timer.hpp \
libtorrent/asio/deadline_timer_service.hpp \
libtorrent/asio/detail/bind_handler.hpp \
libtorrent/asio/detail/buffer_resize_guard.hpp \
libtorrent/asio/detail/buffered_stream_storage.hpp \
libtorrent/asio/detail/call_stack.hpp \
libtorrent/asio/detail/const_buffers_iterator.hpp \
libtorrent/asio/detail/consuming_buffers.hpp \
libtorrent/asio/detail/deadline_timer_service.hpp \
libtorrent/asio/detail/epoll_reactor.hpp \
libtorrent/asio/detail/epoll_reactor_fwd.hpp \
libtorrent/asio/detail/event.hpp \
libtorrent/asio/detail/fd_set_adapter.hpp \
libtorrent/asio/detail/handler_alloc_helpers.hpp \
libtorrent/asio/detail/handler_invoke_helpers.hpp \
libtorrent/asio/detail/hash_map.hpp \
libtorrent/asio/detail/io_control.hpp \
libtorrent/asio/detail/kqueue_reactor.hpp \
libtorrent/asio/detail/kqueue_reactor_fwd.hpp \
libtorrent/asio/detail/local_free_on_block_exit.hpp \
libtorrent/asio/detail/mutex.hpp \
libtorrent/asio/detail/noncopyable.hpp \
libtorrent/asio/detail/null_event.hpp \
libtorrent/asio/detail/null_mutex.hpp \
libtorrent/asio/detail/null_signal_blocker.hpp \
libtorrent/asio/detail/null_thread.hpp \
libtorrent/asio/detail/null_tss_ptr.hpp \
libtorrent/asio/detail/old_win_sdk_compat.hpp \
libtorrent/asio/detail/pipe_select_interrupter.hpp \
libtorrent/asio/detail/pop_options.hpp \
libtorrent/asio/detail/posix_event.hpp \
libtorrent/asio/detail/posix_fd_set_adapter.hpp \
libtorrent/asio/detail/posix_mutex.hpp \
libtorrent/asio/detail/posix_signal_blocker.hpp \
libtorrent/asio/detail/posix_thread.hpp \
libtorrent/asio/detail/posix_tss_ptr.hpp \
libtorrent/asio/detail/push_options.hpp \
libtorrent/asio/detail/reactive_socket_service.hpp \
libtorrent/asio/detail/reactor_op_queue.hpp \
libtorrent/asio/detail/resolver_service.hpp \
libtorrent/asio/detail/scoped_lock.hpp \
libtorrent/asio/detail/select_interrupter.hpp \
libtorrent/asio/detail/select_reactor.hpp \
libtorrent/asio/detail/select_reactor_fwd.hpp \
libtorrent/asio/detail/service_registry.hpp \
libtorrent/asio/detail/service_registry_fwd.hpp \
libtorrent/asio/detail/service_base.hpp \
libtorrent/asio/detail/service_id.hpp \
libtorrent/asio/detail/signal_blocker.hpp \
libtorrent/asio/detail/signal_init.hpp \
libtorrent/asio/detail/socket_holder.hpp \
libtorrent/asio/detail/socket_ops.hpp \
libtorrent/asio/detail/socket_option.hpp \
libtorrent/asio/detail/socket_select_interrupter.hpp \
libtorrent/asio/detail/socket_types.hpp \
libtorrent/asio/detail/strand_service.hpp \
libtorrent/asio/detail/task_io_service.hpp \
libtorrent/asio/detail/task_io_service_fwd.hpp \
libtorrent/asio/detail/thread.hpp \
libtorrent/asio/detail/throw_error.hpp \
libtorrent/asio/detail/timer_queue.hpp \
libtorrent/asio/detail/timer_queue_base.hpp \
libtorrent/asio/detail/tss_ptr.hpp \
libtorrent/asio/detail/win_event.hpp \
libtorrent/asio/detail/win_fd_set_adapter.hpp \
libtorrent/asio/detail/win_iocp_io_service.hpp \
libtorrent/asio/detail/win_iocp_io_service_fwd.hpp \
libtorrent/asio/detail/win_iocp_operation.hpp \
libtorrent/asio/detail/win_iocp_socket_service.hpp \
libtorrent/asio/detail/win_mutex.hpp \
libtorrent/asio/detail/win_signal_blocker.hpp \
libtorrent/asio/detail/win_thread.hpp \
libtorrent/asio/detail/win_tss_ptr.hpp \
libtorrent/asio/detail/winsock_init.hpp \
libtorrent/asio/detail/wrapped_handler.hpp \
libtorrent/asio/error.hpp \
libtorrent/asio/error_code.hpp \
libtorrent/asio/handler_alloc_hook.hpp \
libtorrent/asio/handler_invoke_hook.hpp \
libtorrent/asio/impl/error_code.ipp \
libtorrent/asio/impl/io_service.ipp \
libtorrent/asio/impl/read.ipp \
libtorrent/asio/impl/read_until.ipp \
libtorrent/asio/impl/write.ipp \
libtorrent/asio/io_service.hpp \
libtorrent/asio/ip/address.hpp \
libtorrent/asio/ip/address_v4.hpp \
libtorrent/asio/ip/address_v6.hpp \
libtorrent/asio/ip/basic_endpoint.hpp \
libtorrent/asio/ip/basic_resolver.hpp \
libtorrent/asio/ip/basic_resolver_entry.hpp \
libtorrent/asio/ip/basic_resolver_iterator.hpp \
libtorrent/asio/ip/basic_resolver_query.hpp \
libtorrent/asio/ip/detail/socket_option.hpp \
libtorrent/asio/ip/host_name.hpp \
libtorrent/asio/ip/multicast.hpp \
libtorrent/asio/ip/resolver_query_base.hpp \
libtorrent/asio/ip/resolver_service.hpp \
libtorrent/asio/ip/tcp.hpp \
libtorrent/asio/ip/udp.hpp \
libtorrent/asio/is_read_buffered.hpp \
libtorrent/asio/is_write_buffered.hpp \
libtorrent/asio/placeholders.hpp \
libtorrent/asio/read.hpp \
libtorrent/asio/read_until.hpp \
libtorrent/asio/socket_acceptor_service.hpp \
libtorrent/asio/socket_base.hpp \
libtorrent/asio/ssl/basic_context.hpp \
libtorrent/asio/ssl/context.hpp \
libtorrent/asio/ssl/context_base.hpp \
libtorrent/asio/ssl/context_service.hpp \
libtorrent/asio/ssl/detail/openssl_context_service.hpp \
libtorrent/asio/ssl/detail/openssl_init.hpp \
libtorrent/asio/ssl/detail/openssl_operation.hpp \
libtorrent/asio/ssl/detail/openssl_stream_service.hpp \
libtorrent/asio/ssl/detail/openssl_types.hpp \
libtorrent/asio/ssl/stream.hpp \
libtorrent/asio/ssl/stream_base.hpp \
libtorrent/asio/ssl/stream_service.hpp \
libtorrent/asio/ssl.hpp \
libtorrent/asio/strand.hpp \
libtorrent/asio/stream_socket_service.hpp \
libtorrent/asio/streambuf.hpp \
libtorrent/asio/system_error.hpp \
libtorrent/asio/thread.hpp \
libtorrent/asio/time_traits.hpp \
libtorrent/asio/write.hpp

View file

@ -0,0 +1,74 @@
//
// asio.hpp
// ~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_HPP
#define ASIO_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/basic_datagram_socket.hpp"
#include "asio/basic_deadline_timer.hpp"
#include "asio/basic_io_object.hpp"
#include "asio/basic_socket_acceptor.hpp"
#include "asio/basic_socket_iostream.hpp"
#include "asio/basic_socket_streambuf.hpp"
#include "asio/basic_stream_socket.hpp"
#include "asio/basic_streambuf.hpp"
#include "asio/buffer.hpp"
#include "asio/buffered_read_stream_fwd.hpp"
#include "asio/buffered_read_stream.hpp"
#include "asio/buffered_stream_fwd.hpp"
#include "asio/buffered_stream.hpp"
#include "asio/buffered_write_stream_fwd.hpp"
#include "asio/buffered_write_stream.hpp"
#include "asio/completion_condition.hpp"
#include "asio/datagram_socket_service.hpp"
#include "asio/deadline_timer_service.hpp"
#include "asio/deadline_timer.hpp"
#include "asio/error.hpp"
#include "asio/error_code.hpp"
#include "asio/handler_alloc_hook.hpp"
#include "asio/handler_invoke_hook.hpp"
#include "asio/io_service.hpp"
#include "asio/ip/address.hpp"
#include "asio/ip/address_v4.hpp"
#include "asio/ip/address_v6.hpp"
#include "asio/ip/basic_endpoint.hpp"
#include "asio/ip/basic_resolver.hpp"
#include "asio/ip/basic_resolver_entry.hpp"
#include "asio/ip/basic_resolver_iterator.hpp"
#include "asio/ip/basic_resolver_query.hpp"
#include "asio/ip/host_name.hpp"
#include "asio/ip/multicast.hpp"
#include "asio/ip/resolver_query_base.hpp"
#include "asio/ip/resolver_service.hpp"
#include "asio/ip/tcp.hpp"
#include "asio/ip/udp.hpp"
#include "asio/ip/unicast.hpp"
#include "asio/ip/v6_only.hpp"
#include "asio/is_read_buffered.hpp"
#include "asio/is_write_buffered.hpp"
#include "asio/placeholders.hpp"
#include "asio/read.hpp"
#include "asio/read_until.hpp"
#include "asio/socket_acceptor_service.hpp"
#include "asio/socket_base.hpp"
#include "asio/strand.hpp"
#include "asio/stream_socket_service.hpp"
#include "asio/streambuf.hpp"
#include "asio/system_error.hpp"
#include "asio/thread.hpp"
#include "asio/time_traits.hpp"
#include "asio/version.hpp"
#include "asio/write.hpp"
#endif // ASIO_HPP

View file

@ -0,0 +1,45 @@
/basic_datagram_socket.hpp/1.40/Thu Jan 4 05:44:43 2007//
/basic_deadline_timer.hpp/1.23/Sun May 20 00:49:02 2007//
/basic_io_object.hpp/1.8/Thu Jan 4 05:44:43 2007//
/basic_socket.hpp/1.16/Mon Jan 8 22:12:45 2007//
/basic_socket_acceptor.hpp/1.58/Fri Feb 9 05:47:48 2007//
/basic_socket_iostream.hpp/1.8/Thu Jan 18 11:41:36 2007//
/basic_socket_streambuf.hpp/1.6/Thu Jan 18 11:41:36 2007//
/basic_stream_socket.hpp/1.69/Mon Jan 8 22:12:45 2007//
/basic_streambuf.hpp/1.12/Thu Jan 4 10:23:31 2007//
/buffer.hpp/1.23/Thu Jun 21 14:03:36 2007//
/buffered_read_stream.hpp/1.17/Thu Jan 4 05:44:43 2007//
/buffered_read_stream_fwd.hpp/1.5/Thu Jan 4 05:44:43 2007//
/buffered_stream.hpp/1.32/Thu Jan 4 05:44:43 2007//
/buffered_stream_fwd.hpp/1.9/Thu Jan 4 05:44:43 2007//
/buffered_write_stream.hpp/1.17/Thu Jan 4 05:44:43 2007//
/buffered_write_stream_fwd.hpp/1.5/Thu Jan 4 05:44:43 2007//
/completion_condition.hpp/1.5/Thu Jan 4 05:44:43 2007//
/datagram_socket_service.hpp/1.34/Mon Jan 8 22:12:45 2007//
/deadline_timer.hpp/1.6/Thu Jan 4 05:44:43 2007//
/deadline_timer_service.hpp/1.29/Mon Jan 8 02:47:13 2007//
/error.hpp/1.39/Mon Jan 8 22:12:45 2007//
/error_code.hpp/1.4/Mon Jan 8 22:12:45 2007//
/handler_alloc_hook.hpp/1.11/Thu Jan 4 05:44:43 2007//
/handler_invoke_hook.hpp/1.3/Thu Jan 4 05:44:43 2007//
/io_service.hpp/1.24/Sun May 20 00:49:02 2007//
/is_read_buffered.hpp/1.6/Thu Jan 4 05:44:43 2007//
/is_write_buffered.hpp/1.6/Thu Jan 4 05:44:43 2007//
/placeholders.hpp/1.10/Thu Jan 4 05:44:43 2007//
/read.hpp/1.22/Thu Jan 4 05:44:43 2007//
/read_until.hpp/1.8/Thu Jan 4 05:44:44 2007//
/socket_acceptor_service.hpp/1.34/Fri Feb 9 05:47:48 2007//
/socket_base.hpp/1.23/Mon Jan 8 23:45:36 2007//
/ssl.hpp/1.4/Thu Jan 4 05:44:44 2007//
/strand.hpp/1.6/Tue May 8 13:13:55 2007//
/stream_socket_service.hpp/1.35/Mon Jan 8 22:12:46 2007//
/streambuf.hpp/1.3/Thu Jan 4 05:44:44 2007//
/system_error.hpp/1.3/Thu Jan 4 05:44:44 2007//
/thread.hpp/1.15/Thu Jan 4 05:44:44 2007//
/time_traits.hpp/1.9/Thu Jan 4 05:44:44 2007//
/version.hpp/1.1/Tue May 8 12:17:36 2007//
/write.hpp/1.21/Thu Jan 4 05:44:44 2007//
D/detail////
D/impl////
D/ip////
D/ssl////

View file

@ -0,0 +1 @@
asio/include/asio

View file

@ -0,0 +1 @@
:pserver:anonymous@asio.cvs.sourceforge.net:/cvsroot/asio

View file

@ -0,0 +1,803 @@
//
// basic_datagram_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_DATAGRAM_SOCKET_HPP
#define ASIO_BASIC_DATAGRAM_SOCKET_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_socket.hpp"
#include "asio/datagram_socket_service.hpp"
#include "asio/error.hpp"
#include "asio/detail/throw_error.hpp"
namespace asio {
/// Provides datagram-oriented socket functionality.
/**
* The basic_datagram_socket class template provides asynchronous and blocking
* datagram-oriented socket functionality.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
template <typename Protocol,
typename DatagramSocketService = datagram_socket_service<Protocol> >
class basic_datagram_socket
: public basic_socket<Protocol, DatagramSocketService>
{
public:
/// The native representation of a socket.
typedef typename DatagramSocketService::native_type native_type;
/// The protocol type.
typedef Protocol protocol_type;
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
/// Construct a basic_datagram_socket without opening it.
/**
* This constructor creates a datagram socket without opening it. The open()
* function must be called before data can be sent or received on the socket.
*
* @param io_service The io_service object that the datagram socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
*/
explicit basic_datagram_socket(asio::io_service& io_service)
: basic_socket<Protocol, DatagramSocketService>(io_service)
{
}
/// Construct and open a basic_datagram_socket.
/**
* This constructor creates and opens a datagram socket.
*
* @param io_service The io_service object that the datagram socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
basic_datagram_socket(asio::io_service& io_service,
const protocol_type& protocol)
: basic_socket<Protocol, DatagramSocketService>(io_service, protocol)
{
}
/// Construct a basic_datagram_socket, opening it and binding it to the given
/// local endpoint.
/**
* This constructor creates a datagram socket and automatically opens it bound
* to the specified endpoint on the local machine. The protocol used is the
* protocol associated with the given endpoint.
*
* @param io_service The io_service object that the datagram socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
*
* @param endpoint An endpoint on the local machine to which the datagram
* socket will be bound.
*
* @throws asio::system_error Thrown on failure.
*/
basic_datagram_socket(asio::io_service& io_service,
const endpoint_type& endpoint)
: basic_socket<Protocol, DatagramSocketService>(io_service, endpoint)
{
}
/// Construct a basic_datagram_socket on an existing native socket.
/**
* This constructor creates a datagram socket object to hold an existing
* native socket.
*
* @param io_service The io_service object that the datagram socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @param native_socket The new underlying socket implementation.
*
* @throws asio::system_error Thrown on failure.
*/
basic_datagram_socket(asio::io_service& io_service,
const protocol_type& protocol, const native_type& native_socket)
: basic_socket<Protocol, DatagramSocketService>(
io_service, protocol, native_socket)
{
}
/// Send some data on a connected socket.
/**
* This function is used to send data on the datagram socket. The function
* call will block until the data has been sent successfully or an error
* occurs.
*
* @param buffers One ore more data buffers to be sent on the socket.
*
* @returns The number of bytes sent.
*
* @throws asio::system_error Thrown on failure.
*
* @note The send operation can only be used with a connected socket. Use
* the send_to function to send data on an unconnected datagram socket.
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
* @code socket.send(asio::buffer(data, size)); @endcode
* See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence>
std::size_t send(const ConstBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->service.send(this->implementation, buffers, 0, ec);
asio::detail::throw_error(ec);
return s;
}
/// Send some data on a connected socket.
/**
* This function is used to send data on the datagram socket. The function
* call will block until the data has been sent successfully or an error
* occurs.
*
* @param buffers One ore more data buffers to be sent on the socket.
*
* @param flags Flags specifying how the send call is to be made.
*
* @returns The number of bytes sent.
*
* @throws asio::system_error Thrown on failure.
*
* @note The send operation can only be used with a connected socket. Use
* the send_to function to send data on an unconnected datagram socket.
*/
template <typename ConstBufferSequence>
std::size_t send(const ConstBufferSequence& buffers,
socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->service.send(
this->implementation, buffers, flags, ec);
asio::detail::throw_error(ec);
return s;
}
/// Send some data on a connected socket.
/**
* This function is used to send data on the datagram socket. The function
* call will block until the data has been sent successfully or an error
* occurs.
*
* @param buffers One or more data buffers to be sent on the socket.
*
* @param flags Flags specifying how the send call is to be made.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes sent.
*
* @note The send operation can only be used with a connected socket. Use
* the send_to function to send data on an unconnected datagram socket.
*/
template <typename ConstBufferSequence>
std::size_t send(const ConstBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return this->service.send(this->implementation, buffers, flags, ec);
}
/// Start an asynchronous send on a connected socket.
/**
* This function is used to send data on the datagram socket. The function
* call will block until the data has been sent successfully or an error
* occurs.
*
* @param buffers One or more data buffers to be sent on the socket. Although
* the buffers object may be copied as necessary, ownership of the underlying
* memory blocks is retained by the caller, which must guarantee that they
* remain valid until the handler is called.
*
* @param handler The handler to be called when the send operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @note The async_send operation can only be used with a connected socket.
* Use the async_send_to function to send data on an unconnected datagram
* socket.
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
* @code
* socket.async_send(asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence, typename WriteHandler>
void async_send(const ConstBufferSequence& buffers, WriteHandler handler)
{
this->service.async_send(this->implementation, buffers, 0, handler);
}
/// Start an asynchronous send on a connected socket.
/**
* This function is used to send data on the datagram socket. The function
* call will block until the data has been sent successfully or an error
* occurs.
*
* @param buffers One or more data buffers to be sent on the socket. Although
* the buffers object may be copied as necessary, ownership of the underlying
* memory blocks is retained by the caller, which must guarantee that they
* remain valid until the handler is called.
*
* @param flags Flags specifying how the send call is to be made.
*
* @param handler The handler to be called when the send operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @note The async_send operation can only be used with a connected socket.
* Use the async_send_to function to send data on an unconnected datagram
* socket.
*/
template <typename ConstBufferSequence, typename WriteHandler>
void async_send(const ConstBufferSequence& buffers,
socket_base::message_flags flags, WriteHandler handler)
{
this->service.async_send(this->implementation, buffers, flags, handler);
}
/// Send a datagram to the specified endpoint.
/**
* This function is used to send a datagram to the specified remote endpoint.
* The function call will block until the data has been sent successfully or
* an error occurs.
*
* @param buffers One or more data buffers to be sent to the remote endpoint.
*
* @param destination The remote endpoint to which the data will be sent.
*
* @returns The number of bytes sent.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
* @code
* asio::ip::udp::endpoint destination(
* asio::ip::address::from_string("1.2.3.4"), 12345);
* socket.send_to(asio::buffer(data, size), destination);
* @endcode
* See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence>
std::size_t send_to(const ConstBufferSequence& buffers,
const endpoint_type& destination)
{
asio::error_code ec;
std::size_t s = this->service.send_to(
this->implementation, buffers, destination, 0, ec);
asio::detail::throw_error(ec);
return s;
}
/// Send a datagram to the specified endpoint.
/**
* This function is used to send a datagram to the specified remote endpoint.
* The function call will block until the data has been sent successfully or
* an error occurs.
*
* @param buffers One or more data buffers to be sent to the remote endpoint.
*
* @param destination The remote endpoint to which the data will be sent.
*
* @param flags Flags specifying how the send call is to be made.
*
* @returns The number of bytes sent.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ConstBufferSequence>
std::size_t send_to(const ConstBufferSequence& buffers,
const endpoint_type& destination, socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->service.send_to(
this->implementation, buffers, destination, flags, ec);
asio::detail::throw_error(ec);
return s;
}
/// Send a datagram to the specified endpoint.
/**
* This function is used to send a datagram to the specified remote endpoint.
* The function call will block until the data has been sent successfully or
* an error occurs.
*
* @param buffers One or more data buffers to be sent to the remote endpoint.
*
* @param destination The remote endpoint to which the data will be sent.
*
* @param flags Flags specifying how the send call is to be made.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes sent.
*/
template <typename ConstBufferSequence>
std::size_t send_to(const ConstBufferSequence& buffers,
const endpoint_type& destination, socket_base::message_flags flags,
asio::error_code& ec)
{
return this->service.send_to(this->implementation,
buffers, destination, flags, ec);
}
/// Start an asynchronous send.
/**
* This function is used to asynchronously send a datagram to the specified
* remote endpoint. The function call always returns immediately.
*
* @param buffers One or more data buffers to be sent to the remote endpoint.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param destination The remote endpoint to which the data will be sent.
* Copies will be made of the endpoint as required.
*
* @param handler The handler to be called when the send operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
* @code
* asio::ip::udp::endpoint destination(
* asio::ip::address::from_string("1.2.3.4"), 12345);
* socket.async_send_to(
* asio::buffer(data, size), destination, handler);
* @endcode
* See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence, typename WriteHandler>
void async_send_to(const ConstBufferSequence& buffers,
const endpoint_type& destination, WriteHandler handler)
{
this->service.async_send_to(this->implementation, buffers, destination, 0,
handler);
}
/// Start an asynchronous send.
/**
* This function is used to asynchronously send a datagram to the specified
* remote endpoint. The function call always returns immediately.
*
* @param buffers One or more data buffers to be sent to the remote endpoint.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param flags Flags specifying how the send call is to be made.
*
* @param destination The remote endpoint to which the data will be sent.
* Copies will be made of the endpoint as required.
*
* @param handler The handler to be called when the send operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*/
template <typename ConstBufferSequence, typename WriteHandler>
void async_send_to(const ConstBufferSequence& buffers,
const endpoint_type& destination, socket_base::message_flags flags,
WriteHandler handler)
{
this->service.async_send_to(this->implementation, buffers, destination,
flags, handler);
}
/// Receive some data on a connected socket.
/**
* This function is used to receive data on the datagram socket. The function
* call will block until data has been received successfully or an error
* occurs.
*
* @param buffers One or more buffers into which the data will be received.
*
* @returns The number of bytes received.
*
* @throws asio::system_error Thrown on failure.
*
* @note The receive operation can only be used with a connected socket. Use
* the receive_from function to receive data on an unconnected datagram
* socket.
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code socket.receive(asio::buffer(data, size)); @endcode
* See the @ref buffer documentation for information on receiving into
* multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence>
std::size_t receive(const MutableBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->service.receive(
this->implementation, buffers, 0, ec);
asio::detail::throw_error(ec);
return s;
}
/// Receive some data on a connected socket.
/**
* This function is used to receive data on the datagram socket. The function
* call will block until data has been received successfully or an error
* occurs.
*
* @param buffers One or more buffers into which the data will be received.
*
* @param flags Flags specifying how the receive call is to be made.
*
* @returns The number of bytes received.
*
* @throws asio::system_error Thrown on failure.
*
* @note The receive operation can only be used with a connected socket. Use
* the receive_from function to receive data on an unconnected datagram
* socket.
*/
template <typename MutableBufferSequence>
std::size_t receive(const MutableBufferSequence& buffers,
socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->service.receive(
this->implementation, buffers, flags, ec);
asio::detail::throw_error(ec);
return s;
}
/// Receive some data on a connected socket.
/**
* This function is used to receive data on the datagram socket. The function
* call will block until data has been received successfully or an error
* occurs.
*
* @param buffers One or more buffers into which the data will be received.
*
* @param flags Flags specifying how the receive call is to be made.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes received.
*
* @note The receive operation can only be used with a connected socket. Use
* the receive_from function to receive data on an unconnected datagram
* socket.
*/
template <typename MutableBufferSequence>
std::size_t receive(const MutableBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return this->service.receive(this->implementation, buffers, flags, ec);
}
/// Start an asynchronous receive on a connected socket.
/**
* This function is used to asynchronously receive data from the datagram
* socket. The function call always returns immediately.
*
* @param buffers One or more buffers into which the data will be received.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param handler The handler to be called when the receive operation
* completes. Copies will be made of the handler as required. The function
* signature of the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @note The async_receive operation can only be used with a connected socket.
* Use the async_receive_from function to receive data on an unconnected
* datagram socket.
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code
* socket.async_receive(asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on receiving into
* multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence, typename ReadHandler>
void async_receive(const MutableBufferSequence& buffers, ReadHandler handler)
{
this->service.async_receive(this->implementation, buffers, 0, handler);
}
/// Start an asynchronous receive on a connected socket.
/**
* This function is used to asynchronously receive data from the datagram
* socket. The function call always returns immediately.
*
* @param buffers One or more buffers into which the data will be received.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param flags Flags specifying how the receive call is to be made.
*
* @param handler The handler to be called when the receive operation
* completes. Copies will be made of the handler as required. The function
* signature of the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @note The async_receive operation can only be used with a connected socket.
* Use the async_receive_from function to receive data on an unconnected
* datagram socket.
*/
template <typename MutableBufferSequence, typename ReadHandler>
void async_receive(const MutableBufferSequence& buffers,
socket_base::message_flags flags, ReadHandler handler)
{
this->service.async_receive(this->implementation, buffers, flags, handler);
}
/// Receive a datagram with the endpoint of the sender.
/**
* This function is used to receive a datagram. The function call will block
* until data has been received successfully or an error occurs.
*
* @param buffers One or more buffers into which the data will be received.
*
* @param sender_endpoint An endpoint object that receives the endpoint of
* the remote sender of the datagram.
*
* @returns The number of bytes received.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code
* asio::ip::udp::endpoint sender_endpoint;
* socket.receive_from(
* asio::buffer(data, size), sender_endpoint);
* @endcode
* See the @ref buffer documentation for information on receiving into
* multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence>
std::size_t receive_from(const MutableBufferSequence& buffers,
endpoint_type& sender_endpoint)
{
asio::error_code ec;
std::size_t s = this->service.receive_from(
this->implementation, buffers, sender_endpoint, 0, ec);
asio::detail::throw_error(ec);
return s;
}
/// Receive a datagram with the endpoint of the sender.
/**
* This function is used to receive a datagram. The function call will block
* until data has been received successfully or an error occurs.
*
* @param buffers One or more buffers into which the data will be received.
*
* @param sender_endpoint An endpoint object that receives the endpoint of
* the remote sender of the datagram.
*
* @param flags Flags specifying how the receive call is to be made.
*
* @returns The number of bytes received.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename MutableBufferSequence>
std::size_t receive_from(const MutableBufferSequence& buffers,
endpoint_type& sender_endpoint, socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->service.receive_from(
this->implementation, buffers, sender_endpoint, flags, ec);
asio::detail::throw_error(ec);
return s;
}
/// Receive a datagram with the endpoint of the sender.
/**
* This function is used to receive a datagram. The function call will block
* until data has been received successfully or an error occurs.
*
* @param buffers One or more buffers into which the data will be received.
*
* @param sender_endpoint An endpoint object that receives the endpoint of
* the remote sender of the datagram.
*
* @param flags Flags specifying how the receive call is to be made.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes received.
*/
template <typename MutableBufferSequence>
std::size_t receive_from(const MutableBufferSequence& buffers,
endpoint_type& sender_endpoint, socket_base::message_flags flags,
asio::error_code& ec)
{
return this->service.receive_from(this->implementation, buffers,
sender_endpoint, flags, ec);
}
/// Start an asynchronous receive.
/**
* This function is used to asynchronously receive a datagram. The function
* call always returns immediately.
*
* @param buffers One or more buffers into which the data will be received.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param sender_endpoint An endpoint object that receives the endpoint of
* the remote sender of the datagram. Ownership of the sender_endpoint object
* is retained by the caller, which must guarantee that it is valid until the
* handler is called.
*
* @param handler The handler to be called when the receive operation
* completes. Copies will be made of the handler as required. The function
* signature of the handler must be:
* @code void handler(
* const asio::system_error& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code socket.async_receive_from(
* asio::buffer(data, size), 0, sender_endpoint, handler); @endcode
* See the @ref buffer documentation for information on receiving into
* multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence, typename ReadHandler>
void async_receive_from(const MutableBufferSequence& buffers,
endpoint_type& sender_endpoint, ReadHandler handler)
{
this->service.async_receive_from(this->implementation, buffers,
sender_endpoint, 0, handler);
}
/// Start an asynchronous receive.
/**
* This function is used to asynchronously receive a datagram. The function
* call always returns immediately.
*
* @param buffers One or more buffers into which the data will be received.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param sender_endpoint An endpoint object that receives the endpoint of
* the remote sender of the datagram. Ownership of the sender_endpoint object
* is retained by the caller, which must guarantee that it is valid until the
* handler is called.
*
* @param flags Flags specifying how the receive call is to be made.
*
* @param handler The handler to be called when the receive operation
* completes. Copies will be made of the handler as required. The function
* signature of the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*/
template <typename MutableBufferSequence, typename ReadHandler>
void async_receive_from(const MutableBufferSequence& buffers,
endpoint_type& sender_endpoint, socket_base::message_flags flags,
ReadHandler handler)
{
this->service.async_receive_from(this->implementation, buffers,
sender_endpoint, flags, handler);
}
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_DATAGRAM_SOCKET_HPP

View file

@ -0,0 +1,381 @@
//
// basic_deadline_timer.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_DEADLINE_TIMER_HPP
#define ASIO_BASIC_DEADLINE_TIMER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_io_object.hpp"
#include "asio/deadline_timer_service.hpp"
#include "asio/error.hpp"
#include "asio/detail/throw_error.hpp"
namespace asio {
/// Provides waitable timer functionality.
/**
* The basic_deadline_timer class template provides the ability to perform a
* blocking or asynchronous wait for a timer to expire.
*
* Most applications will use the asio::deadline_timer typedef.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*
* @par Examples
* Performing a blocking wait:
* @code
* // Construct a timer without setting an expiry time.
* asio::deadline_timer timer(io_service);
*
* // Set an expiry time relative to now.
* timer.expires_from_now(boost::posix_time::seconds(5));
*
* // Wait for the timer to expire.
* timer.wait();
* @endcode
*
* @par
* Performing an asynchronous wait:
* @code
* void handler(const asio::error_code& error)
* {
* if (!error)
* {
* // Timer expired.
* }
* }
*
* ...
*
* // Construct a timer with an absolute expiry time.
* asio::deadline_timer timer(io_service,
* boost::posix_time::time_from_string("2005-12-07 23:59:59.000"));
*
* // Start an asynchronous wait.
* timer.async_wait(handler);
* @endcode
*
* @par Changing an active deadline_timer's expiry time
*
* Changing the expiry time of a timer while there are pending asynchronous
* waits causes those wait operations to be cancelled. To ensure that the action
* associated with the timer is performed only once, use something like this:
* used:
*
* @code
* void on_some_event()
* {
* if (my_timer.expires_from_now(seconds(5)) > 0)
* {
* // We managed to cancel the timer. Start new asynchronous wait.
* my_timer.async_wait(on_timeout);
* }
* else
* {
* // Too late, timer has already expired!
* }
* }
*
* void on_timeout(const asio::error_code& e)
* {
* if (e != asio::error::operation_aborted)
* {
* // Timer was not cancelled, take necessary action.
* }
* }
* @endcode
*
* @li The asio::basic_deadline_timer::expires_from_now() function
* cancels any pending asynchronous waits, and returns the number of
* asynchronous waits that were cancelled. If it returns 0 then you were too
* late and the wait handler has already been executed, or will soon be
* executed. If it returns 1 then the wait handler was successfully cancelled.
*
* @li If a wait handler is cancelled, the asio::error_code passed to
* it contains the value asio::error::operation_aborted.
*/
template <typename Time,
typename TimeTraits = asio::time_traits<Time>,
typename TimerService = deadline_timer_service<Time, TimeTraits> >
class basic_deadline_timer
: public basic_io_object<TimerService>
{
public:
/// The time traits type.
typedef TimeTraits traits_type;
/// The time type.
typedef typename traits_type::time_type time_type;
/// The duration type.
typedef typename traits_type::duration_type duration_type;
/// Constructor.
/**
* This constructor creates a timer without setting an expiry time. The
* expires_at() or expires_from_now() functions must be called to set an
* expiry time before the timer can be waited on.
*
* @param io_service The io_service object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
*/
explicit basic_deadline_timer(asio::io_service& io_service)
: basic_io_object<TimerService>(io_service)
{
}
/// Constructor to set a particular expiry time as an absolute time.
/**
* This constructor creates a timer and sets the expiry time.
*
* @param io_service The io_service object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, expressed
* as an absolute time.
*/
basic_deadline_timer(asio::io_service& io_service,
const time_type& expiry_time)
: basic_io_object<TimerService>(io_service)
{
asio::error_code ec;
this->service.expires_at(this->implementation, expiry_time, ec);
asio::detail::throw_error(ec);
}
/// Constructor to set a particular expiry time relative to now.
/**
* This constructor creates a timer and sets the expiry time.
*
* @param io_service The io_service object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, relative to
* now.
*/
basic_deadline_timer(asio::io_service& io_service,
const duration_type& expiry_time)
: basic_io_object<TimerService>(io_service)
{
asio::error_code ec;
this->service.expires_from_now(this->implementation, expiry_time, ec);
asio::detail::throw_error(ec);
}
/// Cancel any asynchronous operations that are waiting on the timer.
/**
* This function forces the completion of any pending asynchronous wait
* operations against the timer. The handler for each cancelled operation will
* be invoked with the asio::error::operation_aborted error code.
*
* Cancelling the timer does not change the expiry time.
*
* @return The number of asynchronous operations that were cancelled.
*
* @throws asio::system_error Thrown on failure.
*/
std::size_t cancel()
{
asio::error_code ec;
std::size_t s = this->service.cancel(this->implementation, ec);
asio::detail::throw_error(ec);
return s;
}
/// Cancel any asynchronous operations that are waiting on the timer.
/**
* This function forces the completion of any pending asynchronous wait
* operations against the timer. The handler for each cancelled operation will
* be invoked with the asio::error::operation_aborted error code.
*
* Cancelling the timer does not change the expiry time.
*
* @param ec Set to indicate what error occurred, if any.
*
* @return The number of asynchronous operations that were cancelled.
*/
std::size_t cancel(asio::error_code& ec)
{
return this->service.cancel(this->implementation, ec);
}
/// Get the timer's expiry time as an absolute time.
/**
* This function may be used to obtain the timer's current expiry time.
* Whether the timer has expired or not does not affect this value.
*/
time_type expires_at() const
{
return this->service.expires_at(this->implementation);
}
/// Set the timer's expiry time as an absolute time.
/**
* This function sets the expiry time. Any pending asynchronous wait
* operations will be cancelled. The handler for each cancelled operation will
* be invoked with the asio::error::operation_aborted error code.
*
* @param expiry_time The expiry time to be used for the timer.
*
* @return The number of asynchronous operations that were cancelled.
*
* @throws asio::system_error Thrown on failure.
*/
std::size_t expires_at(const time_type& expiry_time)
{
asio::error_code ec;
std::size_t s = this->service.expires_at(
this->implementation, expiry_time, ec);
asio::detail::throw_error(ec);
return s;
}
/// Set the timer's expiry time as an absolute time.
/**
* This function sets the expiry time. Any pending asynchronous wait
* operations will be cancelled. The handler for each cancelled operation will
* be invoked with the asio::error::operation_aborted error code.
*
* @param expiry_time The expiry time to be used for the timer.
*
* @param ec Set to indicate what error occurred, if any.
*
* @return The number of asynchronous operations that were cancelled.
*/
std::size_t expires_at(const time_type& expiry_time,
asio::error_code& ec)
{
return this->service.expires_at(this->implementation, expiry_time, ec);
}
/// Get the timer's expiry time relative to now.
/**
* This function may be used to obtain the timer's current expiry time.
* Whether the timer has expired or not does not affect this value.
*/
duration_type expires_from_now() const
{
return this->service.expires_from_now(this->implementation);
}
/// Set the timer's expiry time relative to now.
/**
* This function sets the expiry time. Any pending asynchronous wait
* operations will be cancelled. The handler for each cancelled operation will
* be invoked with the asio::error::operation_aborted error code.
*
* @param expiry_time The expiry time to be used for the timer.
*
* @return The number of asynchronous operations that were cancelled.
*
* @throws asio::system_error Thrown on failure.
*/
std::size_t expires_from_now(const duration_type& expiry_time)
{
asio::error_code ec;
std::size_t s = this->service.expires_from_now(
this->implementation, expiry_time, ec);
asio::detail::throw_error(ec);
return s;
}
/// Set the timer's expiry time relative to now.
/**
* This function sets the expiry time. Any pending asynchronous wait
* operations will be cancelled. The handler for each cancelled operation will
* be invoked with the asio::error::operation_aborted error code.
*
* @param expiry_time The expiry time to be used for the timer.
*
* @param ec Set to indicate what error occurred, if any.
*
* @return The number of asynchronous operations that were cancelled.
*/
std::size_t expires_from_now(const duration_type& expiry_time,
asio::error_code& ec)
{
return this->service.expires_from_now(
this->implementation, expiry_time, ec);
}
/// Perform a blocking wait on the timer.
/**
* This function is used to wait for the timer to expire. This function
* blocks and does not return until the timer has expired.
*
* @throws asio::system_error Thrown on failure.
*/
void wait()
{
asio::error_code ec;
this->service.wait(this->implementation, ec);
asio::detail::throw_error(ec);
}
/// Perform a blocking wait on the timer.
/**
* This function is used to wait for the timer to expire. This function
* blocks and does not return until the timer has expired.
*
* @param ec Set to indicate what error occurred, if any.
*/
void wait(asio::error_code& ec)
{
this->service.wait(this->implementation, ec);
}
/// Start an asynchronous wait on the timer.
/**
* This function may be used to initiate an asynchronous wait against the
* timer. It always returns immediately.
*
* For each call to async_wait(), the supplied handler will be called exactly
* once. The handler will be called when:
*
* @li The timer has expired.
*
* @li The timer was cancelled, in which case the handler is passed the error
* code asio::error::operation_aborted.
*
* @param handler The handler to be called when the timer expires. Copies
* will be made of the handler as required. The function signature of the
* handler must be:
* @code void handler(
* const asio::error_code& error // Result of operation.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*/
template <typename WaitHandler>
void async_wait(WaitHandler handler)
{
this->service.async_wait(this->implementation, handler);
}
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_DEADLINE_TIMER_HPP

View file

@ -0,0 +1,75 @@
//
// basic_io_object.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_IO_OBJECT_HPP
#define ASIO_BASIC_IO_OBJECT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
/// Base class for all I/O objects.
template <typename IoObjectService>
class basic_io_object
: private noncopyable
{
public:
/// The type of the service that will be used to provide I/O operations.
typedef IoObjectService service_type;
/// The underlying implementation type of I/O object.
typedef typename service_type::implementation_type implementation_type;
/// Get the io_service associated with the object.
/**
* This function may be used to obtain the io_service object that the I/O
* object uses to dispatch handlers for asynchronous operations.
*
* @return A reference to the io_service object that the I/O object will use
* to dispatch handlers. Ownership is not transferred to the caller.
*/
asio::io_service& io_service()
{
return service.io_service();
}
protected:
/// Construct a basic_io_object.
explicit basic_io_object(asio::io_service& io_service)
: service(asio::use_service<IoObjectService>(io_service))
{
service.construct(implementation);
}
/// Protected destructor to prevent deletion through this type.
~basic_io_object()
{
service.destroy(implementation);
}
// The backend service implementation.
service_type& service;
// The underlying native implementation.
implementation_type implementation;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_IO_OBJECT_HPP

View file

@ -0,0 +1,972 @@
//
// basic_socket.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_SOCKET_HPP
#define ASIO_BASIC_SOCKET_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/basic_io_object.hpp"
#include "asio/error.hpp"
#include "asio/socket_base.hpp"
#include "asio/detail/throw_error.hpp"
namespace asio {
/// Provides socket functionality.
/**
* The basic_socket class template provides functionality that is common to both
* stream-oriented and datagram-oriented sockets.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
template <typename Protocol, typename SocketService>
class basic_socket
: public basic_io_object<SocketService>,
public socket_base
{
public:
/// The native representation of a socket.
typedef typename SocketService::native_type native_type;
/// The protocol type.
typedef Protocol protocol_type;
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
/// A basic_socket is always the lowest layer.
typedef basic_socket<Protocol, SocketService> lowest_layer_type;
/// Construct a basic_socket without opening it.
/**
* This constructor creates a socket without opening it.
*
* @param io_service The io_service object that the socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*/
explicit basic_socket(asio::io_service& io_service)
: basic_io_object<SocketService>(io_service)
{
}
/// Construct and open a basic_socket.
/**
* This constructor creates and opens a socket.
*
* @param io_service The io_service object that the socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
basic_socket(asio::io_service& io_service,
const protocol_type& protocol)
: basic_io_object<SocketService>(io_service)
{
asio::error_code ec;
this->service.open(this->implementation, protocol, ec);
asio::detail::throw_error(ec);
}
/// Construct a basic_socket, opening it and binding it to the given local
/// endpoint.
/**
* This constructor creates a socket and automatically opens it bound to the
* specified endpoint on the local machine. The protocol used is the protocol
* associated with the given endpoint.
*
* @param io_service The io_service object that the socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param endpoint An endpoint on the local machine to which the socket will
* be bound.
*
* @throws asio::system_error Thrown on failure.
*/
basic_socket(asio::io_service& io_service,
const endpoint_type& endpoint)
: basic_io_object<SocketService>(io_service)
{
asio::error_code ec;
this->service.open(this->implementation, endpoint.protocol(), ec);
asio::detail::throw_error(ec);
this->service.bind(this->implementation, endpoint, ec);
asio::detail::throw_error(ec);
}
/// Construct a basic_socket on an existing native socket.
/**
* This constructor creates a socket object to hold an existing native socket.
*
* @param io_service The io_service object that the socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @param native_socket A native socket.
*
* @throws asio::system_error Thrown on failure.
*/
basic_socket(asio::io_service& io_service,
const protocol_type& protocol, const native_type& native_socket)
: basic_io_object<SocketService>(io_service)
{
asio::error_code ec;
this->service.assign(this->implementation, protocol, native_socket, ec);
asio::detail::throw_error(ec);
}
/// Get a reference to the lowest layer.
/**
* This function returns a reference to the lowest layer in a stack of
* layers. Since a basic_socket cannot contain any further layers, it simply
* returns a reference to itself.
*
* @return A reference to the lowest layer in the stack of layers. Ownership
* is not transferred to the caller.
*/
lowest_layer_type& lowest_layer()
{
return *this;
}
/// Open the socket using the specified protocol.
/**
* This function opens the socket so that it will use the specified protocol.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* @code
* asio::ip::tcp::socket socket(io_service);
* socket.open(asio::ip::tcp::v4());
* @endcode
*/
void open(const protocol_type& protocol = protocol_type())
{
asio::error_code ec;
this->service.open(this->implementation, protocol, ec);
asio::detail::throw_error(ec);
}
/// Open the socket using the specified protocol.
/**
* This function opens the socket so that it will use the specified protocol.
*
* @param protocol An object specifying which protocol is to be used.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* @code
* asio::ip::tcp::socket socket(io_service);
* asio::error_code ec;
* socket.open(asio::ip::tcp::v4(), ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
asio::error_code open(const protocol_type& protocol,
asio::error_code& ec)
{
return this->service.open(this->implementation, protocol, ec);
}
/// Assign an existing native socket to the socket.
/*
* This function opens the socket to hold an existing native socket.
*
* @param protocol An object specifying which protocol is to be used.
*
* @param native_socket A native socket.
*
* @throws asio::system_error Thrown on failure.
*/
void assign(const protocol_type& protocol, const native_type& native_socket)
{
asio::error_code ec;
this->service.assign(this->implementation, protocol, native_socket, ec);
asio::detail::throw_error(ec);
}
/// Assign an existing native socket to the socket.
/*
* This function opens the socket to hold an existing native socket.
*
* @param protocol An object specifying which protocol is to be used.
*
* @param native_socket A native socket.
*
* @param ec Set to indicate what error occurred, if any.
*/
asio::error_code assign(const protocol_type& protocol,
const native_type& native_socket, asio::error_code& ec)
{
return this->service.assign(this->implementation,
protocol, native_socket, ec);
}
/// Determine whether the socket is open.
bool is_open() const
{
return this->service.is_open(this->implementation);
}
/// Close the socket.
/**
* This function is used to close the socket. Any asynchronous send, receive
* or connect operations will be cancelled immediately, and will complete
* with the asio::error::operation_aborted error.
*
* @throws asio::system_error Thrown on failure.
*/
void close()
{
asio::error_code ec;
this->service.close(this->implementation, ec);
asio::detail::throw_error(ec);
}
/// Close the socket.
/**
* This function is used to close the socket. Any asynchronous send, receive
* or connect operations will be cancelled immediately, and will complete
* with the asio::error::operation_aborted error.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::error_code ec;
* socket.close(ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
asio::error_code close(asio::error_code& ec)
{
return this->service.close(this->implementation, ec);
}
/// Get the native socket representation.
/**
* This function may be used to obtain the underlying representation of the
* socket. This is intended to allow access to native socket functionality
* that is not otherwise provided.
*/
native_type native()
{
return this->service.native(this->implementation);
}
/// Cancel all asynchronous operations associated with the socket.
/**
* This function causes all outstanding asynchronous connect, send and receive
* operations to finish immediately, and the handlers for cancelled operations
* will be passed the asio::error::operation_aborted error.
*
* @throws asio::system_error Thrown on failure.
*/
void cancel()
{
asio::error_code ec;
this->service.cancel(this->implementation, ec);
asio::detail::throw_error(ec);
}
/// Cancel all asynchronous operations associated with the socket.
/**
* This function causes all outstanding asynchronous connect, send and receive
* operations to finish immediately, and the handlers for cancelled operations
* will be passed the asio::error::operation_aborted error.
*
* @param ec Set to indicate what error occurred, if any.
*/
asio::error_code cancel(asio::error_code& ec)
{
return this->service.cancel(this->implementation, ec);
}
/// Determine whether the socket is at the out-of-band data mark.
/**
* This function is used to check whether the socket input is currently
* positioned at the out-of-band data mark.
*
* @return A bool indicating whether the socket is at the out-of-band data
* mark.
*
* @throws asio::system_error Thrown on failure.
*/
bool at_mark() const
{
asio::error_code ec;
bool b = this->service.at_mark(this->implementation, ec);
asio::detail::throw_error(ec);
return b;
}
/// Determine whether the socket is at the out-of-band data mark.
/**
* This function is used to check whether the socket input is currently
* positioned at the out-of-band data mark.
*
* @param ec Set to indicate what error occurred, if any.
*
* @return A bool indicating whether the socket is at the out-of-band data
* mark.
*/
bool at_mark(asio::error_code& ec) const
{
return this->service.at_mark(this->implementation, ec);
}
/// Determine the number of bytes available for reading.
/**
* This function is used to determine the number of bytes that may be read
* without blocking.
*
* @return The number of bytes that may be read without blocking, or 0 if an
* error occurs.
*
* @throws asio::system_error Thrown on failure.
*/
std::size_t available() const
{
asio::error_code ec;
std::size_t s = this->service.available(this->implementation, ec);
asio::detail::throw_error(ec);
return s;
}
/// Determine the number of bytes available for reading.
/**
* This function is used to determine the number of bytes that may be read
* without blocking.
*
* @param ec Set to indicate what error occurred, if any.
*
* @return The number of bytes that may be read without blocking, or 0 if an
* error occurs.
*/
std::size_t available(asio::error_code& ec) const
{
return this->service.available(this->implementation, ec);
}
/// Bind the socket to the given local endpoint.
/**
* This function binds the socket to the specified endpoint on the local
* machine.
*
* @param endpoint An endpoint on the local machine to which the socket will
* be bound.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* @code
* asio::ip::tcp::socket socket(io_service);
* socket.open(asio::ip::tcp::v4());
* socket.bind(asio::ip::tcp::endpoint(
* asio::ip::tcp::v4(), 12345));
* @endcode
*/
void bind(const endpoint_type& endpoint)
{
asio::error_code ec;
this->service.bind(this->implementation, endpoint, ec);
asio::detail::throw_error(ec);
}
/// Bind the socket to the given local endpoint.
/**
* This function binds the socket to the specified endpoint on the local
* machine.
*
* @param endpoint An endpoint on the local machine to which the socket will
* be bound.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* @code
* asio::ip::tcp::socket socket(io_service);
* socket.open(asio::ip::tcp::v4());
* asio::error_code ec;
* socket.bind(asio::ip::tcp::endpoint(
* asio::ip::tcp::v4(), 12345), ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
asio::error_code bind(const endpoint_type& endpoint,
asio::error_code& ec)
{
return this->service.bind(this->implementation, endpoint, ec);
}
/// Connect the socket to the specified endpoint.
/**
* This function is used to connect a socket to the specified remote endpoint.
* The function call will block until the connection is successfully made or
* an error occurs.
*
* The socket is automatically opened if it is not already open. If the
* connect fails, and the socket was automatically opened, the socket is
* returned to the closed state.
*
* @param peer_endpoint The remote endpoint to which the socket will be
* connected.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* @code
* asio::ip::tcp::socket socket(io_service);
* asio::ip::tcp::endpoint endpoint(
* asio::ip::address::from_string("1.2.3.4"), 12345);
* socket.connect(endpoint);
* @endcode
*/
void connect(const endpoint_type& peer_endpoint)
{
asio::error_code ec;
if (!is_open())
{
this->service.open(this->implementation, peer_endpoint.protocol(), ec);
asio::detail::throw_error(ec);
}
this->service.connect(this->implementation, peer_endpoint, ec);
asio::detail::throw_error(ec);
}
/// Connect the socket to the specified endpoint.
/**
* This function is used to connect a socket to the specified remote endpoint.
* The function call will block until the connection is successfully made or
* an error occurs.
*
* The socket is automatically opened if it is not already open. If the
* connect fails, and the socket was automatically opened, the socket is
* returned to the closed state.
*
* @param peer_endpoint The remote endpoint to which the socket will be
* connected.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* @code
* asio::ip::tcp::socket socket(io_service);
* asio::ip::tcp::endpoint endpoint(
* asio::ip::address::from_string("1.2.3.4"), 12345);
* asio::error_code ec;
* socket.connect(endpoint, ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
asio::error_code connect(const endpoint_type& peer_endpoint,
asio::error_code& ec)
{
if (!is_open())
{
if (this->service.open(this->implementation,
peer_endpoint.protocol(), ec))
{
return ec;
}
}
return this->service.connect(this->implementation, peer_endpoint, ec);
}
/// Start an asynchronous connect.
/**
* This function is used to asynchronously connect a socket to the specified
* remote endpoint. The function call always returns immediately.
*
* The socket is automatically opened if it is not already open. If the
* connect fails, and the socket was automatically opened, the socket is
* returned to the closed state.
*
* @param peer_endpoint The remote endpoint to which the socket will be
* connected. Copies will be made of the endpoint object as required.
*
* @param handler The handler to be called when the connection operation
* completes. Copies will be made of the handler as required. The function
* signature of the handler must be:
* @code void handler(
* const asio::error_code& error // Result of operation
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @par Example
* @code
* void connect_handler(const asio::error_code& error)
* {
* if (!error)
* {
* // Connect succeeded.
* }
* }
*
* ...
*
* asio::ip::tcp::socket socket(io_service);
* asio::ip::tcp::endpoint endpoint(
* asio::ip::address::from_string("1.2.3.4"), 12345);
* socket.async_connect(endpoint, connect_handler);
* @endcode
*/
template <typename ConnectHandler>
void async_connect(const endpoint_type& peer_endpoint, ConnectHandler handler)
{
if (!is_open())
{
asio::error_code ec;
if (this->service.open(this->implementation,
peer_endpoint.protocol(), ec))
{
this->io_service().post(asio::detail::bind_handler(handler, ec));
return;
}
}
this->service.async_connect(this->implementation, peer_endpoint, handler);
}
/// Set an option on the socket.
/**
* This function is used to set an option on the socket.
*
* @param option The new option value to be set on the socket.
*
* @throws asio::system_error Thrown on failure.
*
* @sa SettableSocketOption @n
* asio::socket_base::broadcast @n
* asio::socket_base::do_not_route @n
* asio::socket_base::keep_alive @n
* asio::socket_base::linger @n
* asio::socket_base::receive_buffer_size @n
* asio::socket_base::receive_low_watermark @n
* asio::socket_base::reuse_address @n
* asio::socket_base::send_buffer_size @n
* asio::socket_base::send_low_watermark @n
* asio::ip::multicast::join_group @n
* asio::ip::multicast::leave_group @n
* asio::ip::multicast::enable_loopback @n
* asio::ip::multicast::outbound_interface @n
* asio::ip::multicast::hops @n
* asio::ip::tcp::no_delay
*
* @par Example
* Setting the IPPROTO_TCP/TCP_NODELAY option:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::no_delay option(true);
* socket.set_option(option);
* @endcode
*/
template <typename SettableSocketOption>
void set_option(const SettableSocketOption& option)
{
asio::error_code ec;
this->service.set_option(this->implementation, option, ec);
asio::detail::throw_error(ec);
}
/// Set an option on the socket.
/**
* This function is used to set an option on the socket.
*
* @param option The new option value to be set on the socket.
*
* @param ec Set to indicate what error occurred, if any.
*
* @sa SettableSocketOption @n
* asio::socket_base::broadcast @n
* asio::socket_base::do_not_route @n
* asio::socket_base::keep_alive @n
* asio::socket_base::linger @n
* asio::socket_base::receive_buffer_size @n
* asio::socket_base::receive_low_watermark @n
* asio::socket_base::reuse_address @n
* asio::socket_base::send_buffer_size @n
* asio::socket_base::send_low_watermark @n
* asio::ip::multicast::join_group @n
* asio::ip::multicast::leave_group @n
* asio::ip::multicast::enable_loopback @n
* asio::ip::multicast::outbound_interface @n
* asio::ip::multicast::hops @n
* asio::ip::tcp::no_delay
*
* @par Example
* Setting the IPPROTO_TCP/TCP_NODELAY option:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::no_delay option(true);
* asio::error_code ec;
* socket.set_option(option, ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename SettableSocketOption>
asio::error_code set_option(const SettableSocketOption& option,
asio::error_code& ec)
{
return this->service.set_option(this->implementation, option, ec);
}
/// Get an option from the socket.
/**
* This function is used to get the current value of an option on the socket.
*
* @param option The option value to be obtained from the socket.
*
* @throws asio::system_error Thrown on failure.
*
* @sa GettableSocketOption @n
* asio::socket_base::broadcast @n
* asio::socket_base::do_not_route @n
* asio::socket_base::keep_alive @n
* asio::socket_base::linger @n
* asio::socket_base::receive_buffer_size @n
* asio::socket_base::receive_low_watermark @n
* asio::socket_base::reuse_address @n
* asio::socket_base::send_buffer_size @n
* asio::socket_base::send_low_watermark @n
* asio::ip::multicast::join_group @n
* asio::ip::multicast::leave_group @n
* asio::ip::multicast::enable_loopback @n
* asio::ip::multicast::outbound_interface @n
* asio::ip::multicast::hops @n
* asio::ip::tcp::no_delay
*
* @par Example
* Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::socket::keep_alive option;
* socket.get_option(option);
* bool is_set = option.get();
* @endcode
*/
template <typename GettableSocketOption>
void get_option(GettableSocketOption& option) const
{
asio::error_code ec;
this->service.get_option(this->implementation, option, ec);
asio::detail::throw_error(ec);
}
/// Get an option from the socket.
/**
* This function is used to get the current value of an option on the socket.
*
* @param option The option value to be obtained from the socket.
*
* @param ec Set to indicate what error occurred, if any.
*
* @sa GettableSocketOption @n
* asio::socket_base::broadcast @n
* asio::socket_base::do_not_route @n
* asio::socket_base::keep_alive @n
* asio::socket_base::linger @n
* asio::socket_base::receive_buffer_size @n
* asio::socket_base::receive_low_watermark @n
* asio::socket_base::reuse_address @n
* asio::socket_base::send_buffer_size @n
* asio::socket_base::send_low_watermark @n
* asio::ip::multicast::join_group @n
* asio::ip::multicast::leave_group @n
* asio::ip::multicast::enable_loopback @n
* asio::ip::multicast::outbound_interface @n
* asio::ip::multicast::hops @n
* asio::ip::tcp::no_delay
*
* @par Example
* Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::socket::keep_alive option;
* asio::error_code ec;
* socket.get_option(option, ec);
* if (ec)
* {
* // An error occurred.
* }
* bool is_set = option.get();
* @endcode
*/
template <typename GettableSocketOption>
asio::error_code get_option(GettableSocketOption& option,
asio::error_code& ec) const
{
return this->service.get_option(this->implementation, option, ec);
}
/// Perform an IO control command on the socket.
/**
* This function is used to execute an IO control command on the socket.
*
* @param command The IO control command to be performed on the socket.
*
* @throws asio::system_error Thrown on failure.
*
* @sa IoControlCommand @n
* asio::socket_base::bytes_readable @n
* asio::socket_base::non_blocking_io
*
* @par Example
* Getting the number of bytes ready to read:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::socket::bytes_readable command;
* socket.io_control(command);
* std::size_t bytes_readable = command.get();
* @endcode
*/
template <typename IoControlCommand>
void io_control(IoControlCommand& command)
{
asio::error_code ec;
this->service.io_control(this->implementation, command, ec);
asio::detail::throw_error(ec);
}
/// Perform an IO control command on the socket.
/**
* This function is used to execute an IO control command on the socket.
*
* @param command The IO control command to be performed on the socket.
*
* @param ec Set to indicate what error occurred, if any.
*
* @sa IoControlCommand @n
* asio::socket_base::bytes_readable @n
* asio::socket_base::non_blocking_io
*
* @par Example
* Getting the number of bytes ready to read:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::socket::bytes_readable command;
* asio::error_code ec;
* socket.io_control(command, ec);
* if (ec)
* {
* // An error occurred.
* }
* std::size_t bytes_readable = command.get();
* @endcode
*/
template <typename IoControlCommand>
asio::error_code io_control(IoControlCommand& command,
asio::error_code& ec)
{
return this->service.io_control(this->implementation, command, ec);
}
/// Get the local endpoint of the socket.
/**
* This function is used to obtain the locally bound endpoint of the socket.
*
* @returns An object that represents the local endpoint of the socket.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
* @endcode
*/
endpoint_type local_endpoint() const
{
asio::error_code ec;
endpoint_type ep = this->service.local_endpoint(this->implementation, ec);
asio::detail::throw_error(ec);
return ep;
}
/// Get the local endpoint of the socket.
/**
* This function is used to obtain the locally bound endpoint of the socket.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns An object that represents the local endpoint of the socket.
* Returns a default-constructed endpoint object if an error occurred.
*
* @par Example
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::error_code ec;
* asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
endpoint_type local_endpoint(asio::error_code& ec) const
{
return this->service.local_endpoint(this->implementation, ec);
}
/// Get the remote endpoint of the socket.
/**
* This function is used to obtain the remote endpoint of the socket.
*
* @returns An object that represents the remote endpoint of the socket.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
* @endcode
*/
endpoint_type remote_endpoint() const
{
asio::error_code ec;
endpoint_type ep = this->service.remote_endpoint(this->implementation, ec);
asio::detail::throw_error(ec);
return ep;
}
/// Get the remote endpoint of the socket.
/**
* This function is used to obtain the remote endpoint of the socket.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns An object that represents the remote endpoint of the socket.
* Returns a default-constructed endpoint object if an error occurred.
*
* @par Example
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::error_code ec;
* asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
endpoint_type remote_endpoint(asio::error_code& ec) const
{
return this->service.remote_endpoint(this->implementation, ec);
}
/// Disable sends or receives on the socket.
/**
* This function is used to disable send operations, receive operations, or
* both.
*
* @param what Determines what types of operation will no longer be allowed.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* Shutting down the send side of the socket:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* socket.shutdown(asio::ip::tcp::socket::shutdown_send);
* @endcode
*/
void shutdown(shutdown_type what)
{
asio::error_code ec;
this->service.shutdown(this->implementation, what, ec);
asio::detail::throw_error(ec);
}
/// Disable sends or receives on the socket.
/**
* This function is used to disable send operations, receive operations, or
* both.
*
* @param what Determines what types of operation will no longer be allowed.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* Shutting down the send side of the socket:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::error_code ec;
* socket.shutdown(asio::ip::tcp::socket::shutdown_send, ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
asio::error_code shutdown(shutdown_type what,
asio::error_code& ec)
{
return this->service.shutdown(this->implementation, what, ec);
}
protected:
/// Protected destructor to prevent deletion through this type.
~basic_socket()
{
}
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_SOCKET_HPP

View file

@ -0,0 +1,824 @@
//
// basic_socket_acceptor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_SOCKET_ACCEPTOR_HPP
#define ASIO_BASIC_SOCKET_ACCEPTOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/basic_io_object.hpp"
#include "asio/basic_socket.hpp"
#include "asio/error.hpp"
#include "asio/socket_acceptor_service.hpp"
#include "asio/socket_base.hpp"
#include "asio/detail/throw_error.hpp"
namespace asio {
/// Provides the ability to accept new connections.
/**
* The basic_socket_acceptor class template is used for accepting new socket
* connections.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*
* @par Example
* Opening a socket acceptor with the SO_REUSEADDR option enabled:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port);
* acceptor.open(endpoint.protocol());
* acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true));
* acceptor.bind(endpoint);
* acceptor.listen();
* @endcode
*/
template <typename Protocol,
typename SocketAcceptorService = socket_acceptor_service<Protocol> >
class basic_socket_acceptor
: public basic_io_object<SocketAcceptorService>,
public socket_base
{
public:
/// The native representation of an acceptor.
typedef typename SocketAcceptorService::native_type native_type;
/// The protocol type.
typedef Protocol protocol_type;
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
/// Construct an acceptor without opening it.
/**
* This constructor creates an acceptor without opening it to listen for new
* connections. The open() function must be called before the acceptor can
* accept new socket connections.
*
* @param io_service The io_service object that the acceptor will use to
* dispatch handlers for any asynchronous operations performed on the
* acceptor.
*/
explicit basic_socket_acceptor(asio::io_service& io_service)
: basic_io_object<SocketAcceptorService>(io_service)
{
}
/// Construct an open acceptor.
/**
* This constructor creates an acceptor and automatically opens it.
*
* @param io_service The io_service object that the acceptor will use to
* dispatch handlers for any asynchronous operations performed on the
* acceptor.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
basic_socket_acceptor(asio::io_service& io_service,
const protocol_type& protocol)
: basic_io_object<SocketAcceptorService>(io_service)
{
asio::error_code ec;
this->service.open(this->implementation, protocol, ec);
asio::detail::throw_error(ec);
}
/// Construct an acceptor opened on the given endpoint.
/**
* This constructor creates an acceptor and automatically opens it to listen
* for new connections on the specified endpoint.
*
* @param io_service The io_service object that the acceptor will use to
* dispatch handlers for any asynchronous operations performed on the
* acceptor.
*
* @param endpoint An endpoint on the local machine on which the acceptor
* will listen for new connections.
*
* @param reuse_addr Whether the constructor should set the socket option
* socket_base::reuse_address.
*
* @throws asio::system_error Thrown on failure.
*
* @note This constructor is equivalent to the following code:
* @code
* basic_socket_acceptor<Protocol> acceptor(io_service);
* acceptor.open(endpoint.protocol());
* if (reuse_addr)
* acceptor.set_option(socket_base::reuse_address(true));
* acceptor.bind(endpoint);
* acceptor.listen(listen_backlog);
* @endcode
*/
basic_socket_acceptor(asio::io_service& io_service,
const endpoint_type& endpoint, bool reuse_addr = true)
: basic_io_object<SocketAcceptorService>(io_service)
{
asio::error_code ec;
this->service.open(this->implementation, endpoint.protocol(), ec);
asio::detail::throw_error(ec);
if (reuse_addr)
{
this->service.set_option(this->implementation,
socket_base::reuse_address(true), ec);
asio::detail::throw_error(ec);
}
this->service.bind(this->implementation, endpoint, ec);
asio::detail::throw_error(ec);
this->service.listen(this->implementation,
socket_base::max_connections, ec);
asio::detail::throw_error(ec);
}
/// Construct a basic_socket_acceptor on an existing native acceptor.
/**
* This constructor creates an acceptor object to hold an existing native
* acceptor.
*
* @param io_service The io_service object that the acceptor will use to
* dispatch handlers for any asynchronous operations performed on the
* acceptor.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @param native_acceptor A native acceptor.
*
* @throws asio::system_error Thrown on failure.
*/
basic_socket_acceptor(asio::io_service& io_service,
const protocol_type& protocol, const native_type& native_acceptor)
: basic_io_object<SocketAcceptorService>(io_service)
{
asio::error_code ec;
this->service.assign(this->implementation, protocol, native_acceptor, ec);
asio::detail::throw_error(ec);
}
/// Open the acceptor using the specified protocol.
/**
* This function opens the socket acceptor so that it will use the specified
* protocol.
*
* @param protocol An object specifying which protocol is to be used.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* acceptor.open(asio::ip::tcp::v4());
* @endcode
*/
void open(const protocol_type& protocol = protocol_type())
{
asio::error_code ec;
this->service.open(this->implementation, protocol, ec);
asio::detail::throw_error(ec);
}
/// Open the acceptor using the specified protocol.
/**
* This function opens the socket acceptor so that it will use the specified
* protocol.
*
* @param protocol An object specifying which protocol is to be used.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* asio::error_code ec;
* acceptor.open(asio::ip::tcp::v4(), ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
asio::error_code open(const protocol_type& protocol,
asio::error_code& ec)
{
return this->service.open(this->implementation, protocol, ec);
}
/// Assigns an existing native acceptor to the acceptor.
/*
* This function opens the acceptor to hold an existing native acceptor.
*
* @param protocol An object specifying which protocol is to be used.
*
* @param native_acceptor A native acceptor.
*
* @throws asio::system_error Thrown on failure.
*/
void assign(const protocol_type& protocol, const native_type& native_acceptor)
{
asio::error_code ec;
this->service.assign(this->implementation, protocol, native_acceptor, ec);
asio::detail::throw_error(ec);
}
/// Assigns an existing native acceptor to the acceptor.
/*
* This function opens the acceptor to hold an existing native acceptor.
*
* @param protocol An object specifying which protocol is to be used.
*
* @param native_acceptor A native acceptor.
*
* @param ec Set to indicate what error occurred, if any.
*/
asio::error_code assign(const protocol_type& protocol,
const native_type& native_acceptor, asio::error_code& ec)
{
return this->service.assign(this->implementation,
protocol, native_acceptor, ec);
}
/// Determine whether the acceptor is open.
bool is_open() const
{
return this->service.is_open(this->implementation);
}
/// Bind the acceptor to the given local endpoint.
/**
* This function binds the socket acceptor to the specified endpoint on the
* local machine.
*
* @param endpoint An endpoint on the local machine to which the socket
* acceptor will be bound.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* acceptor.open(asio::ip::tcp::v4());
* acceptor.bind(asio::ip::tcp::endpoint(12345));
* @endcode
*/
void bind(const endpoint_type& endpoint)
{
asio::error_code ec;
this->service.bind(this->implementation, endpoint, ec);
asio::detail::throw_error(ec);
}
/// Bind the acceptor to the given local endpoint.
/**
* This function binds the socket acceptor to the specified endpoint on the
* local machine.
*
* @param endpoint An endpoint on the local machine to which the socket
* acceptor will be bound.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* acceptor.open(asio::ip::tcp::v4());
* asio::error_code ec;
* acceptor.bind(asio::ip::tcp::endpoint(12345), ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
asio::error_code bind(const endpoint_type& endpoint,
asio::error_code& ec)
{
return this->service.bind(this->implementation, endpoint, ec);
}
/// Place the acceptor into the state where it will listen for new
/// connections.
/**
* This function puts the socket acceptor into the state where it may accept
* new connections.
*
* @param backlog The maximum length of the queue of pending connections.
*
* @throws asio::system_error Thrown on failure.
*/
void listen(int backlog = socket_base::max_connections)
{
asio::error_code ec;
this->service.listen(this->implementation, backlog, ec);
asio::detail::throw_error(ec);
}
/// Place the acceptor into the state where it will listen for new
/// connections.
/**
* This function puts the socket acceptor into the state where it may accept
* new connections.
*
* @param backlog The maximum length of the queue of pending connections.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::error_code ec;
* acceptor.listen(asio::socket_base::max_connections, ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
asio::error_code listen(int backlog, asio::error_code& ec)
{
return this->service.listen(this->implementation, backlog, ec);
}
/// Close the acceptor.
/**
* This function is used to close the acceptor. Any asynchronous accept
* operations will be cancelled immediately.
*
* A subsequent call to open() is required before the acceptor can again be
* used to again perform socket accept operations.
*
* @throws asio::system_error Thrown on failure.
*/
void close()
{
asio::error_code ec;
this->service.close(this->implementation, ec);
asio::detail::throw_error(ec);
}
/// Close the acceptor.
/**
* This function is used to close the acceptor. Any asynchronous accept
* operations will be cancelled immediately.
*
* A subsequent call to open() is required before the acceptor can again be
* used to again perform socket accept operations.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::error_code ec;
* acceptor.close(ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
asio::error_code close(asio::error_code& ec)
{
return this->service.close(this->implementation, ec);
}
/// Get the native acceptor representation.
/**
* This function may be used to obtain the underlying representation of the
* acceptor. This is intended to allow access to native acceptor functionality
* that is not otherwise provided.
*/
native_type native()
{
return this->service.native(this->implementation);
}
/// Cancel all asynchronous operations associated with the acceptor.
/**
* This function causes all outstanding asynchronous connect, send and receive
* operations to finish immediately, and the handlers for cancelled operations
* will be passed the asio::error::operation_aborted error.
*
* @throws asio::system_error Thrown on failure.
*/
void cancel()
{
asio::error_code ec;
this->service.cancel(this->implementation, ec);
asio::detail::throw_error(ec);
}
/// Cancel all asynchronous operations associated with the acceptor.
/**
* This function causes all outstanding asynchronous connect, send and receive
* operations to finish immediately, and the handlers for cancelled operations
* will be passed the asio::error::operation_aborted error.
*
* @param ec Set to indicate what error occurred, if any.
*/
asio::error_code cancel(asio::error_code& ec)
{
return this->service.cancel(this->implementation, ec);
}
/// Set an option on the acceptor.
/**
* This function is used to set an option on the acceptor.
*
* @param option The new option value to be set on the acceptor.
*
* @throws asio::system_error Thrown on failure.
*
* @sa SettableSocketOption @n
* asio::socket_base::reuse_address
* asio::socket_base::enable_connection_aborted
*
* @par Example
* Setting the SOL_SOCKET/SO_REUSEADDR option:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::acceptor::reuse_address option(true);
* acceptor.set_option(option);
* @endcode
*/
template <typename SettableSocketOption>
void set_option(const SettableSocketOption& option)
{
asio::error_code ec;
this->service.set_option(this->implementation, option, ec);
asio::detail::throw_error(ec);
}
/// Set an option on the acceptor.
/**
* This function is used to set an option on the acceptor.
*
* @param option The new option value to be set on the acceptor.
*
* @param ec Set to indicate what error occurred, if any.
*
* @sa SettableSocketOption @n
* asio::socket_base::reuse_address
* asio::socket_base::enable_connection_aborted
*
* @par Example
* Setting the SOL_SOCKET/SO_REUSEADDR option:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::acceptor::reuse_address option(true);
* asio::error_code ec;
* acceptor.set_option(option, ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename SettableSocketOption>
asio::error_code set_option(const SettableSocketOption& option,
asio::error_code& ec)
{
return this->service.set_option(this->implementation, option, ec);
}
/// Get an option from the acceptor.
/**
* This function is used to get the current value of an option on the
* acceptor.
*
* @param option The option value to be obtained from the acceptor.
*
* @throws asio::system_error Thrown on failure.
*
* @sa GettableSocketOption @n
* asio::socket_base::reuse_address
*
* @par Example
* Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::acceptor::reuse_address option;
* acceptor.get_option(option);
* bool is_set = option.get();
* @endcode
*/
template <typename GettableSocketOption>
void get_option(GettableSocketOption& option)
{
asio::error_code ec;
this->service.get_option(this->implementation, option, ec);
asio::detail::throw_error(ec);
}
/// Get an option from the acceptor.
/**
* This function is used to get the current value of an option on the
* acceptor.
*
* @param option The option value to be obtained from the acceptor.
*
* @param ec Set to indicate what error occurred, if any.
*
* @sa GettableSocketOption @n
* asio::socket_base::reuse_address
*
* @par Example
* Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::acceptor::reuse_address option;
* asio::error_code ec;
* acceptor.get_option(option, ec);
* if (ec)
* {
* // An error occurred.
* }
* bool is_set = option.get();
* @endcode
*/
template <typename GettableSocketOption>
asio::error_code get_option(GettableSocketOption& option,
asio::error_code& ec)
{
return this->service.get_option(this->implementation, option, ec);
}
/// Get the local endpoint of the acceptor.
/**
* This function is used to obtain the locally bound endpoint of the acceptor.
*
* @returns An object that represents the local endpoint of the acceptor.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint();
* @endcode
*/
endpoint_type local_endpoint() const
{
asio::error_code ec;
endpoint_type ep = this->service.local_endpoint(this->implementation, ec);
asio::detail::throw_error(ec);
return ep;
}
/// Get the local endpoint of the acceptor.
/**
* This function is used to obtain the locally bound endpoint of the acceptor.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns An object that represents the local endpoint of the acceptor.
* Returns a default-constructed endpoint object if an error occurred and the
* error handler did not throw an exception.
*
* @par Example
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::error_code ec;
* asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
endpoint_type local_endpoint(asio::error_code& ec) const
{
return this->service.local_endpoint(this->implementation, ec);
}
/// Accept a new connection.
/**
* This function is used to accept a new connection from a peer into the
* given socket. The function call will block until a new connection has been
* accepted successfully or an error occurs.
*
* @param peer The socket into which the new connection will be accepted.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::socket socket(io_service);
* acceptor.accept(socket);
* @endcode
*/
template <typename SocketService>
void accept(basic_socket<protocol_type, SocketService>& peer)
{
asio::error_code ec;
this->service.accept(this->implementation, peer, 0, ec);
asio::detail::throw_error(ec);
}
/// Accept a new connection.
/**
* This function is used to accept a new connection from a peer into the
* given socket. The function call will block until a new connection has been
* accepted successfully or an error occurs.
*
* @param peer The socket into which the new connection will be accepted.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::soocket socket(io_service);
* asio::error_code ec;
* acceptor.accept(socket, ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename SocketService>
asio::error_code accept(
basic_socket<protocol_type, SocketService>& peer,
asio::error_code& ec)
{
return this->service.accept(this->implementation, peer, 0, ec);
}
/// Start an asynchronous accept.
/**
* This function is used to asynchronously accept a new connection into a
* socket. The function call always returns immediately.
*
* @param peer The socket into which the new connection will be accepted.
* Ownership of the peer object is retained by the caller, which must
* guarantee that it is valid until the handler is called.
*
* @param handler The handler to be called when the accept operation
* completes. Copies will be made of the handler as required. The function
* signature of the handler must be:
* @code void handler(
* const asio::error_code& error // Result of operation.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @par Example
* @code
* void accept_handler(const asio::error_code& error)
* {
* if (!error)
* {
* // Accept succeeded.
* }
* }
*
* ...
*
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::socket socket(io_service);
* acceptor.async_accept(socket, accept_handler);
* @endcode
*/
template <typename SocketService, typename AcceptHandler>
void async_accept(basic_socket<protocol_type, SocketService>& peer,
AcceptHandler handler)
{
this->service.async_accept(this->implementation, peer, 0, handler);
}
/// Accept a new connection and obtain the endpoint of the peer
/**
* This function is used to accept a new connection from a peer into the
* given socket, and additionally provide the endpoint of the remote peer.
* The function call will block until a new connection has been accepted
* successfully or an error occurs.
*
* @param peer The socket into which the new connection will be accepted.
*
* @param peer_endpoint An endpoint object which will receive the endpoint of
* the remote peer.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::socket socket(io_service);
* asio::ip::tcp::endpoint endpoint;
* acceptor.accept(socket, endpoint);
* @endcode
*/
template <typename SocketService>
void accept(basic_socket<protocol_type, SocketService>& peer,
endpoint_type& peer_endpoint)
{
asio::error_code ec;
this->service.accept(this->implementation, peer, &peer_endpoint, ec);
asio::detail::throw_error(ec);
}
/// Accept a new connection and obtain the endpoint of the peer
/**
* This function is used to accept a new connection from a peer into the
* given socket, and additionally provide the endpoint of the remote peer.
* The function call will block until a new connection has been accepted
* successfully or an error occurs.
*
* @param peer The socket into which the new connection will be accepted.
*
* @param peer_endpoint An endpoint object which will receive the endpoint of
* the remote peer.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::socket socket(io_service);
* asio::ip::tcp::endpoint endpoint;
* asio::error_code ec;
* acceptor.accept(socket, endpoint, ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename SocketService>
asio::error_code accept(
basic_socket<protocol_type, SocketService>& peer,
endpoint_type& peer_endpoint, asio::error_code& ec)
{
return this->service.accept(this->implementation, peer, &peer_endpoint, ec);
}
/// Start an asynchronous accept.
/**
* This function is used to asynchronously accept a new connection into a
* socket, and additionally obtain the endpoint of the remote peer. The
* function call always returns immediately.
*
* @param peer The socket into which the new connection will be accepted.
* Ownership of the peer object is retained by the caller, which must
* guarantee that it is valid until the handler is called.
*
* @param peer_endpoint An endpoint object into which the endpoint of the
* remote peer will be written. Ownership of the peer_endpoint object is
* retained by the caller, which must guarantee that it is valid until the
* handler is called.
*
* @param handler The handler to be called when the accept operation
* completes. Copies will be made of the handler as required. The function
* signature of the handler must be:
* @code void handler(
* const asio::error_code& error // Result of operation.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*/
template <typename SocketService, typename AcceptHandler>
void async_accept(basic_socket<protocol_type, SocketService>& peer,
endpoint_type& peer_endpoint, AcceptHandler handler)
{
this->service.async_accept(this->implementation,
peer, &peer_endpoint, handler);
}
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_SOCKET_ACCEPTOR_HPP

View file

@ -0,0 +1,146 @@
//
// basic_socket_iostream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_SOCKET_IOSTREAM_HPP
#define ASIO_BASIC_SOCKET_IOSTREAM_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/utility/base_from_member.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_socket_streambuf.hpp"
#include "asio/stream_socket_service.hpp"
#if !defined(ASIO_SOCKET_IOSTREAM_MAX_ARITY)
#define ASIO_SOCKET_IOSTREAM_MAX_ARITY 5
#endif // !defined(ASIO_SOCKET_IOSTREAM_MAX_ARITY)
// A macro that should expand to:
// template <typename T1, ..., typename Tn>
// explicit basic_socket_iostream(T1 x1, ..., Tn xn)
// : basic_iostream<char>(&this->boost::base_from_member<
// basic_socket_streambuf<Protocol, StreamSocketService> >::member)
// {
// if (rdbuf()->connect(x1, ..., xn) == 0)
// this->setstate(std::ios_base::failbit);
// }
// This macro should only persist within this file.
#define ASIO_PRIVATE_CTR_DEF(z, n, data) \
template <BOOST_PP_ENUM_PARAMS(n, typename T)> \
explicit basic_socket_iostream(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \
: std::basic_iostream<char>(&this->boost::base_from_member< \
basic_socket_streambuf<Protocol, StreamSocketService> >::member) \
{ \
if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \
this->setstate(std::ios_base::failbit); \
} \
/**/
// A macro that should expand to:
// template <typename T1, ..., typename Tn>
// void connect(T1 x1, ..., Tn xn)
// {
// if (rdbuf()->connect(x1, ..., xn) == 0)
// this->setstate(std::ios_base::failbit);
// }
// This macro should only persist within this file.
#define ASIO_PRIVATE_CONNECT_DEF(z, n, data) \
template <BOOST_PP_ENUM_PARAMS(n, typename T)> \
void connect(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \
{ \
if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \
this->setstate(std::ios_base::failbit); \
} \
/**/
namespace asio {
/// Iostream interface for a socket.
template <typename Protocol,
typename StreamSocketService = stream_socket_service<Protocol> >
class basic_socket_iostream
: public boost::base_from_member<
basic_socket_streambuf<Protocol, StreamSocketService> >,
public std::basic_iostream<char>
{
public:
/// Construct a basic_socket_iostream without establishing a connection.
basic_socket_iostream()
: std::basic_iostream<char>(&this->boost::base_from_member<
basic_socket_streambuf<Protocol, StreamSocketService> >::member)
{
}
#if defined(GENERATING_DOCUMENTATION)
/// Establish a connection to an endpoint corresponding to a resolver query.
/**
* This constructor automatically establishes a connection based on the
* supplied resolver query parameters. The arguments are used to construct
* a resolver query object.
*/
template <typename T1, ..., typename TN>
explicit basic_socket_iostream(T1 t1, ..., TN tn);
#else
BOOST_PP_REPEAT_FROM_TO(
1, BOOST_PP_INC(ASIO_SOCKET_IOSTREAM_MAX_ARITY),
ASIO_PRIVATE_CTR_DEF, _ )
#endif
#if defined(GENERATING_DOCUMENTATION)
/// Establish a connection to an endpoint corresponding to a resolver query.
/**
* This function automatically establishes a connection based on the supplied
* resolver query parameters. The arguments are used to construct a resolver
* query object.
*/
template <typename T1, ..., typename TN>
void connect(T1 t1, ..., TN tn);
#else
BOOST_PP_REPEAT_FROM_TO(
1, BOOST_PP_INC(ASIO_SOCKET_IOSTREAM_MAX_ARITY),
ASIO_PRIVATE_CONNECT_DEF, _ )
#endif
/// Close the connection.
void close()
{
if (rdbuf()->close() == 0)
this->setstate(std::ios_base::failbit);
}
/// Return a pointer to the underlying streambuf.
basic_socket_streambuf<Protocol, StreamSocketService>* rdbuf() const
{
return const_cast<basic_socket_streambuf<Protocol, StreamSocketService>*>(
&this->boost::base_from_member<
basic_socket_streambuf<Protocol, StreamSocketService> >::member);
}
};
} // namespace asio
#undef ASIO_PRIVATE_CTR_DEF
#undef ASIO_PRIVATE_CONNECT_DEF
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_SOCKET_IOSTREAM_HPP

View file

@ -0,0 +1,284 @@
//
// basic_socket_streambuf.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_SOCKET_STREAMBUF_HPP
#define ASIO_BASIC_SOCKET_STREAMBUF_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <streambuf>
#include <boost/array.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/utility/base_from_member.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_socket.hpp"
#include "asio/io_service.hpp"
#include "asio/stream_socket_service.hpp"
#include "asio/detail/throw_error.hpp"
#if !defined(ASIO_SOCKET_STREAMBUF_MAX_ARITY)
#define ASIO_SOCKET_STREAMBUF_MAX_ARITY 5
#endif // !defined(ASIO_SOCKET_STREAMBUF_MAX_ARITY)
// A macro that should expand to:
// template <typename T1, ..., typename Tn>
// basic_socket_streambuf<Protocol, StreamSocketService>* connect(
// T1 x1, ..., Tn xn)
// {
// init_buffers();
// asio::error_code ec;
// this->basic_socket<Protocol, StreamSocketService>::close(ec);
// typedef typename Protocol::resolver_query resolver_query;
// resolver_query query(x1, ..., xn);
// resolve_and_connect(query, ec);
// return !ec ? this : 0;
// }
// This macro should only persist within this file.
#define ASIO_PRIVATE_CONNECT_DEF( z, n, data ) \
template <BOOST_PP_ENUM_PARAMS(n, typename T)> \
basic_socket_streambuf<Protocol, StreamSocketService>* connect( \
BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \
{ \
init_buffers(); \
asio::error_code ec; \
this->basic_socket<Protocol, StreamSocketService>::close(ec); \
typedef typename Protocol::resolver_query resolver_query; \
resolver_query query(BOOST_PP_ENUM_PARAMS(n, x)); \
resolve_and_connect(query, ec); \
return !ec ? this : 0; \
} \
/**/
namespace asio {
/// Iostream streambuf for a socket.
template <typename Protocol,
typename StreamSocketService = stream_socket_service<Protocol> >
class basic_socket_streambuf
: public std::streambuf,
private boost::base_from_member<io_service>,
public basic_socket<Protocol, StreamSocketService>
{
public:
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
/// Construct a basic_socket_streambuf without establishing a connection.
basic_socket_streambuf()
: basic_socket<Protocol, StreamSocketService>(
boost::base_from_member<asio::io_service>::member),
unbuffered_(false)
{
init_buffers();
}
/// Destructor flushes buffered data.
virtual ~basic_socket_streambuf()
{
if (pptr() != pbase())
overflow(traits_type::eof());
}
/// Establish a connection.
/**
* This function establishes a connection to the specified endpoint.
*
* @return \c this if a connection was successfully established, a null
* pointer otherwise.
*/
basic_socket_streambuf<Protocol, StreamSocketService>* connect(
const endpoint_type& endpoint)
{
init_buffers();
asio::error_code ec;
this->basic_socket<Protocol, StreamSocketService>::close(ec);
this->basic_socket<Protocol, StreamSocketService>::connect(endpoint, ec);
return !ec ? this : 0;
}
#if defined(GENERATING_DOCUMENTATION)
/// Establish a connection.
/**
* This function automatically establishes a connection based on the supplied
* resolver query parameters. The arguments are used to construct a resolver
* query object.
*
* @return \c this if a connection was successfully established, a null
* pointer otherwise.
*/
template <typename T1, ..., typename TN>
basic_socket_streambuf<Protocol, StreamSocketService>* connect(
T1 t1, ..., TN tn);
#else
BOOST_PP_REPEAT_FROM_TO(
1, BOOST_PP_INC(ASIO_SOCKET_STREAMBUF_MAX_ARITY),
ASIO_PRIVATE_CONNECT_DEF, _ )
#endif
/// Close the connection.
/**
* @return \c this if a connection was successfully established, a null
* pointer otherwise.
*/
basic_socket_streambuf<Protocol, StreamSocketService>* close()
{
asio::error_code ec;
sync();
this->basic_socket<Protocol, StreamSocketService>::close(ec);
if (!ec)
init_buffers();
return !ec ? this : 0;
}
protected:
int_type underflow()
{
if (gptr() == egptr())
{
asio::error_code ec;
std::size_t bytes_transferred = this->service.receive(
this->implementation,
asio::buffer(asio::buffer(get_buffer_) + putback_max),
0, ec);
if (ec)
return traits_type::eof();
setg(get_buffer_.begin(), get_buffer_.begin() + putback_max,
get_buffer_.begin() + putback_max + bytes_transferred);
return traits_type::to_int_type(*gptr());
}
else
{
return traits_type::eof();
}
}
int_type overflow(int_type c)
{
if (unbuffered_)
{
if (traits_type::eq_int_type(c, traits_type::eof()))
{
// Nothing to do.
return traits_type::not_eof(c);
}
else
{
// Send the single character immediately.
asio::error_code ec;
char_type ch = traits_type::to_char_type(c);
this->service.send(this->implementation,
asio::buffer(&ch, sizeof(char_type)), 0, ec);
if (ec)
return traits_type::eof();
return c;
}
}
else
{
// Send all data in the output buffer.
asio::const_buffer buffer =
asio::buffer(pbase(), pptr() - pbase());
while (asio::buffer_size(buffer) > 0)
{
asio::error_code ec;
std::size_t bytes_transferred = this->service.send(
this->implementation, asio::buffer(buffer),
0, ec);
if (ec)
return traits_type::eof();
buffer = buffer + bytes_transferred;
}
setp(put_buffer_.begin(), put_buffer_.end());
// If the new character is eof then our work here is done.
if (traits_type::eq_int_type(c, traits_type::eof()))
return traits_type::not_eof(c);
// Add the new character to the output buffer.
*pptr() = traits_type::to_char_type(c);
pbump(1);
return c;
}
}
int sync()
{
return overflow(traits_type::eof());
}
std::streambuf* setbuf(char_type* s, std::streamsize n)
{
if (pptr() == pbase() && s == 0 && n == 0)
{
unbuffered_ = true;
setp(0, 0);
return this;
}
return 0;
}
private:
void init_buffers()
{
setg(get_buffer_.begin(),
get_buffer_.begin() + putback_max,
get_buffer_.begin() + putback_max);
if (unbuffered_)
setp(0, 0);
else
setp(put_buffer_.begin(), put_buffer_.end());
}
void resolve_and_connect(const typename Protocol::resolver_query& query,
asio::error_code& ec)
{
typedef typename Protocol::resolver resolver_type;
typedef typename Protocol::resolver_iterator iterator_type;
resolver_type resolver(
boost::base_from_member<asio::io_service>::member);
iterator_type i = resolver.resolve(query, ec);
if (!ec)
{
iterator_type end;
ec = asio::error::host_not_found;
while (ec && i != end)
{
this->basic_socket<Protocol, StreamSocketService>::close();
this->basic_socket<Protocol, StreamSocketService>::connect(*i, ec);
++i;
}
}
}
enum { putback_max = 8 };
enum { buffer_size = 512 };
boost::array<char, buffer_size> get_buffer_;
boost::array<char, buffer_size> put_buffer_;
bool unbuffered_;
};
} // namespace asio
#undef ASIO_PRIVATE_CONNECT_DEF
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_SOCKET_STREAMBUF_HPP

View file

@ -0,0 +1,718 @@
//
// basic_stream_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_STREAM_SOCKET_HPP
#define ASIO_BASIC_STREAM_SOCKET_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_socket.hpp"
#include "asio/error.hpp"
#include "asio/stream_socket_service.hpp"
#include "asio/detail/throw_error.hpp"
namespace asio {
/// Provides stream-oriented socket functionality.
/**
* The basic_stream_socket class template provides asynchronous and blocking
* stream-oriented socket functionality.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
*/
template <typename Protocol,
typename StreamSocketService = stream_socket_service<Protocol> >
class basic_stream_socket
: public basic_socket<Protocol, StreamSocketService>
{
public:
/// The native representation of a socket.
typedef typename StreamSocketService::native_type native_type;
/// The protocol type.
typedef Protocol protocol_type;
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
/// Construct a basic_stream_socket without opening it.
/**
* This constructor creates a stream socket without opening it. The socket
* needs to be opened and then connected or accepted before data can be sent
* or received on it.
*
* @param io_service The io_service object that the stream socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*/
explicit basic_stream_socket(asio::io_service& io_service)
: basic_socket<Protocol, StreamSocketService>(io_service)
{
}
/// Construct and open a basic_stream_socket.
/**
* This constructor creates and opens a stream socket. The socket needs to be
* connected or accepted before data can be sent or received on it.
*
* @param io_service The io_service object that the stream socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
basic_stream_socket(asio::io_service& io_service,
const protocol_type& protocol)
: basic_socket<Protocol, StreamSocketService>(io_service, protocol)
{
}
/// Construct a basic_stream_socket, opening it and binding it to the given
/// local endpoint.
/**
* This constructor creates a stream socket and automatically opens it bound
* to the specified endpoint on the local machine. The protocol used is the
* protocol associated with the given endpoint.
*
* @param io_service The io_service object that the stream socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param endpoint An endpoint on the local machine to which the stream
* socket will be bound.
*
* @throws asio::system_error Thrown on failure.
*/
basic_stream_socket(asio::io_service& io_service,
const endpoint_type& endpoint)
: basic_socket<Protocol, StreamSocketService>(io_service, endpoint)
{
}
/// Construct a basic_stream_socket on an existing native socket.
/**
* This constructor creates a stream socket object to hold an existing native
* socket.
*
* @param io_service The io_service object that the stream socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @param native_socket The new underlying socket implementation.
*
* @throws asio::system_error Thrown on failure.
*/
basic_stream_socket(asio::io_service& io_service,
const protocol_type& protocol, const native_type& native_socket)
: basic_socket<Protocol, StreamSocketService>(
io_service, protocol, native_socket)
{
}
/// Send some data on the socket.
/**
* This function is used to send data on the stream socket. The function
* call will block until one or more bytes of the data has been sent
* successfully, or an until error occurs.
*
* @param buffers One or more data buffers to be sent on the socket.
*
* @returns The number of bytes sent.
*
* @throws asio::system_error Thrown on failure.
*
* @note The send operation may not transmit all of the data to the peer.
* Consider using the @ref write function if you need to ensure that all data
* is written before the blocking operation completes.
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
* @code
* socket.send(asio::buffer(data, size));
* @endcode
* See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence>
std::size_t send(const ConstBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->service.send(
this->implementation, buffers, 0, ec);
asio::detail::throw_error(ec);
return s;
}
/// Send some data on the socket.
/**
* This function is used to send data on the stream socket. The function
* call will block until one or more bytes of the data has been sent
* successfully, or an until error occurs.
*
* @param buffers One or more data buffers to be sent on the socket.
*
* @param flags Flags specifying how the send call is to be made.
*
* @returns The number of bytes sent.
*
* @throws asio::system_error Thrown on failure.
*
* @note The send operation may not transmit all of the data to the peer.
* Consider using the @ref write function if you need to ensure that all data
* is written before the blocking operation completes.
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
* @code
* socket.send(asio::buffer(data, size), 0);
* @endcode
* See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence>
std::size_t send(const ConstBufferSequence& buffers,
socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->service.send(
this->implementation, buffers, flags, ec);
asio::detail::throw_error(ec);
return s;
}
/// Send some data on the socket.
/**
* This function is used to send data on the stream socket. The function
* call will block until one or more bytes of the data has been sent
* successfully, or an until error occurs.
*
* @param buffers One or more data buffers to be sent on the socket.
*
* @param flags Flags specifying how the send call is to be made.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes sent. Returns 0 if an error occurred.
*
* @note The send operation may not transmit all of the data to the peer.
* Consider using the @ref write function if you need to ensure that all data
* is written before the blocking operation completes.
*/
template <typename ConstBufferSequence>
std::size_t send(const ConstBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return this->service.send(this->implementation, buffers, flags, ec);
}
/// Start an asynchronous send.
/**
* This function is used to asynchronously send data on the stream socket.
* The function call always returns immediately.
*
* @param buffers One or more data buffers to be sent on the socket. Although
* the buffers object may be copied as necessary, ownership of the underlying
* memory blocks is retained by the caller, which must guarantee that they
* remain valid until the handler is called.
*
* @param handler The handler to be called when the send operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @note The send operation may not transmit all of the data to the peer.
* Consider using the @ref async_write function if you need to ensure that all
* data is written before the asynchronous operation completes.
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
* @code
* socket.async_send(asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence, typename WriteHandler>
void async_send(const ConstBufferSequence& buffers, WriteHandler handler)
{
this->service.async_send(this->implementation, buffers, 0, handler);
}
/// Start an asynchronous send.
/**
* This function is used to asynchronously send data on the stream socket.
* The function call always returns immediately.
*
* @param buffers One or more data buffers to be sent on the socket. Although
* the buffers object may be copied as necessary, ownership of the underlying
* memory blocks is retained by the caller, which must guarantee that they
* remain valid until the handler is called.
*
* @param flags Flags specifying how the send call is to be made.
*
* @param handler The handler to be called when the send operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @note The send operation may not transmit all of the data to the peer.
* Consider using the @ref async_write function if you need to ensure that all
* data is written before the asynchronous operation completes.
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
* @code
* socket.async_send(asio::buffer(data, size), 0, handler);
* @endcode
* See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence, typename WriteHandler>
void async_send(const ConstBufferSequence& buffers,
socket_base::message_flags flags, WriteHandler handler)
{
this->service.async_send(this->implementation, buffers, flags, handler);
}
/// Receive some data on the socket.
/**
* This function is used to receive data on the stream socket. The function
* call will block until one or more bytes of data has been received
* successfully, or until an error occurs.
*
* @param buffers One or more buffers into which the data will be received.
*
* @returns The number of bytes received.
*
* @throws asio::system_error Thrown on failure. An error code of
* asio::error::eof indicates that the connection was closed by the
* peer.
*
* @note The receive operation may not receive all of the requested number of
* bytes. Consider using the @ref read function if you need to ensure that the
* requested amount of data is read before the blocking operation completes.
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code
* socket.receive(asio::buffer(data, size));
* @endcode
* See the @ref buffer documentation for information on receiving into
* multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence>
std::size_t receive(const MutableBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->service.receive(this->implementation, buffers, 0, ec);
asio::detail::throw_error(ec);
return s;
}
/// Receive some data on the socket.
/**
* This function is used to receive data on the stream socket. The function
* call will block until one or more bytes of data has been received
* successfully, or until an error occurs.
*
* @param buffers One or more buffers into which the data will be received.
*
* @param flags Flags specifying how the receive call is to be made.
*
* @returns The number of bytes received.
*
* @throws asio::system_error Thrown on failure. An error code of
* asio::error::eof indicates that the connection was closed by the
* peer.
*
* @note The receive operation may not receive all of the requested number of
* bytes. Consider using the @ref read function if you need to ensure that the
* requested amount of data is read before the blocking operation completes.
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code
* socket.receive(asio::buffer(data, size), 0);
* @endcode
* See the @ref buffer documentation for information on receiving into
* multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence>
std::size_t receive(const MutableBufferSequence& buffers,
socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->service.receive(
this->implementation, buffers, flags, ec);
asio::detail::throw_error(ec);
return s;
}
/// Receive some data on a connected socket.
/**
* This function is used to receive data on the stream socket. The function
* call will block until one or more bytes of data has been received
* successfully, or until an error occurs.
*
* @param buffers One or more buffers into which the data will be received.
*
* @param flags Flags specifying how the receive call is to be made.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes received. Returns 0 if an error occurred.
*
* @note The receive operation may not receive all of the requested number of
* bytes. Consider using the @ref read function if you need to ensure that the
* requested amount of data is read before the blocking operation completes.
*/
template <typename MutableBufferSequence>
std::size_t receive(const MutableBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return this->service.receive(this->implementation, buffers, flags, ec);
}
/// Start an asynchronous receive.
/**
* This function is used to asynchronously receive data from the stream
* socket. The function call always returns immediately.
*
* @param buffers One or more buffers into which the data will be received.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param handler The handler to be called when the receive operation
* completes. Copies will be made of the handler as required. The function
* signature of the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @note The receive operation may not receive all of the requested number of
* bytes. Consider using the @ref async_read function if you need to ensure
* that the requested amount of data is received before the asynchronous
* operation completes.
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code
* socket.async_receive(asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on receiving into
* multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence, typename ReadHandler>
void async_receive(const MutableBufferSequence& buffers, ReadHandler handler)
{
this->service.async_receive(this->implementation, buffers, 0, handler);
}
/// Start an asynchronous receive.
/**
* This function is used to asynchronously receive data from the stream
* socket. The function call always returns immediately.
*
* @param buffers One or more buffers into which the data will be received.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param flags Flags specifying how the receive call is to be made.
*
* @param handler The handler to be called when the receive operation
* completes. Copies will be made of the handler as required. The function
* signature of the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @note The receive operation may not receive all of the requested number of
* bytes. Consider using the @ref async_read function if you need to ensure
* that the requested amount of data is received before the asynchronous
* operation completes.
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code
* socket.async_receive(asio::buffer(data, size), 0, handler);
* @endcode
* See the @ref buffer documentation for information on receiving into
* multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence, typename ReadHandler>
void async_receive(const MutableBufferSequence& buffers,
socket_base::message_flags flags, ReadHandler handler)
{
this->service.async_receive(this->implementation, buffers, flags, handler);
}
/// Write some data to the socket.
/**
* This function is used to write data to the stream socket. The function call
* will block until one or more bytes of the data has been written
* successfully, or until an error occurs.
*
* @param buffers One or more data buffers to be written to the socket.
*
* @returns The number of bytes written.
*
* @throws asio::system_error Thrown on failure. An error code of
* asio::error::eof indicates that the connection was closed by the
* peer.
*
* @note The write_some operation may not transmit all of the data to the
* peer. Consider using the @ref write function if you need to ensure that
* all data is written before the blocking operation completes.
*
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
* @code
* socket.write_some(asio::buffer(data, size));
* @endcode
* See the @ref buffer documentation for information on writing multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->service.send(this->implementation, buffers, 0, ec);
asio::detail::throw_error(ec);
return s;
}
/// Write some data to the socket.
/**
* This function is used to write data to the stream socket. The function call
* will block until one or more bytes of the data has been written
* successfully, or until an error occurs.
*
* @param buffers One or more data buffers to be written to the socket.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes written. Returns 0 if an error occurred.
*
* @note The write_some operation may not transmit all of the data to the
* peer. Consider using the @ref write function if you need to ensure that
* all data is written before the blocking operation completes.
*/
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers,
asio::error_code& ec)
{
return this->service.send(this->implementation, buffers, 0, ec);
}
/// Start an asynchronous write.
/**
* This function is used to asynchronously write data to the stream socket.
* The function call always returns immediately.
*
* @param buffers One or more data buffers to be written to the socket.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param handler The handler to be called when the write operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes written.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @note The write operation may not transmit all of the data to the peer.
* Consider using the @ref async_write function if you need to ensure that all
* data is written before the asynchronous operation completes.
*
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
* @code
* socket.async_write_some(asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on writing multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence, typename WriteHandler>
void async_write_some(const ConstBufferSequence& buffers,
WriteHandler handler)
{
this->service.async_send(this->implementation, buffers, 0, handler);
}
/// Read some data from the socket.
/**
* This function is used to read data from the stream socket. The function
* call will block until one or more bytes of data has been read successfully,
* or until an error occurs.
*
* @param buffers One or more buffers into which the data will be read.
*
* @returns The number of bytes read.
*
* @throws asio::system_error Thrown on failure. An error code of
* asio::error::eof indicates that the connection was closed by the
* peer.
*
* @note The read_some operation may not read all of the requested number of
* bytes. Consider using the @ref read function if you need to ensure that
* the requested amount of data is read before the blocking operation
* completes.
*
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
* @code
* socket.read_some(asio::buffer(data, size));
* @endcode
* See the @ref buffer documentation for information on reading into multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->service.receive(this->implementation, buffers, 0, ec);
asio::detail::throw_error(ec);
return s;
}
/// Read some data from the socket.
/**
* This function is used to read data from the stream socket. The function
* call will block until one or more bytes of data has been read successfully,
* or until an error occurs.
*
* @param buffers One or more buffers into which the data will be read.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes read. Returns 0 if an error occurred.
*
* @note The read_some operation may not read all of the requested number of
* bytes. Consider using the @ref read function if you need to ensure that
* the requested amount of data is read before the blocking operation
* completes.
*/
template <typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence& buffers,
asio::error_code& ec)
{
return this->service.receive(this->implementation, buffers, 0, ec);
}
/// Start an asynchronous read.
/**
* This function is used to asynchronously read data from the stream socket.
* The function call always returns immediately.
*
* @param buffers One or more buffers into which the data will be read.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param handler The handler to be called when the read operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes read.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @note The read operation may not read all of the requested number of bytes.
* Consider using the @ref async_read function if you need to ensure that the
* requested amount of data is read before the asynchronous operation
* completes.
*
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
* @code
* socket.async_read_some(asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on reading into multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence, typename ReadHandler>
void async_read_some(const MutableBufferSequence& buffers,
ReadHandler handler)
{
this->service.async_receive(this->implementation, buffers, 0, handler);
}
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_STREAM_SOCKET_HPP

View file

@ -0,0 +1,200 @@
//
// basic_streambuf.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_STREAMBUF_HPP
#define ASIO_BASIC_STREAMBUF_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <algorithm>
#include <limits>
#include <memory>
#include <stdexcept>
#include <streambuf>
#include <vector>
#include "asio/detail/pop_options.hpp"
#include "asio/buffer.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
/// Automatically resizable buffer class based on std::streambuf.
template <typename Allocator = std::allocator<char> >
class basic_streambuf
: public std::streambuf,
private noncopyable
{
public:
#if defined(GENERATING_DOCUMENTATION)
/// The type used to represent the get area as a list of buffers.
typedef implementation_defined const_buffers_type;
/// The type used to represent the put area as a list of buffers.
typedef implementation_defined mutable_buffers_type;
#else
typedef asio::const_buffers_1 const_buffers_type;
typedef asio::mutable_buffers_1 mutable_buffers_type;
#endif
/// Construct a buffer with a specified maximum size.
explicit basic_streambuf(
std::size_t max_size = (std::numeric_limits<std::size_t>::max)(),
const Allocator& allocator = Allocator())
: max_size_(max_size),
buffer_(allocator)
{
std::size_t pend = (std::min<std::size_t>)(max_size_, buffer_delta);
buffer_.resize((std::max<std::size_t>)(pend, 1));
setg(&buffer_[0], &buffer_[0], &buffer_[0]);
setp(&buffer_[0], &buffer_[0] + pend);
}
/// Return the size of the get area in characters.
std::size_t size() const
{
return pptr() - gptr();
}
/// Return the maximum size of the buffer.
std::size_t max_size() const
{
return max_size_;
}
/// Get a list of buffers that represents the get area.
const_buffers_type data() const
{
return asio::buffer(asio::const_buffer(gptr(),
(pptr() - gptr()) * sizeof(char_type)));
}
/// Get a list of buffers that represents the put area, with the given size.
mutable_buffers_type prepare(std::size_t size)
{
reserve(size);
return asio::buffer(asio::mutable_buffer(
pptr(), size * sizeof(char_type)));
}
/// Move the start of the put area by the specified number of characters.
void commit(std::size_t n)
{
if (pptr() + n > epptr())
n = epptr() - pptr();
pbump(static_cast<int>(n));
}
/// Move the start of the get area by the specified number of characters.
void consume(std::size_t n)
{
while (n > 0)
{
sbumpc();
--n;
}
}
protected:
enum { buffer_delta = 128 };
int_type underflow()
{
if (gptr() < pptr())
{
setg(&buffer_[0], gptr(), pptr());
return traits_type::to_int_type(*gptr());
}
else
{
return traits_type::eof();
}
}
int_type overflow(int_type c)
{
if (!traits_type::eq_int_type(c, traits_type::eof()))
{
if (pptr() == epptr())
{
std::size_t buffer_size = pptr() - gptr();
if (buffer_size < max_size_ && max_size_ - buffer_size < buffer_delta)
{
reserve(max_size_ - buffer_size);
}
else
{
reserve(buffer_delta);
}
}
*pptr() = traits_type::to_char_type(c);
pbump(1);
return c;
}
return traits_type::not_eof(c);
}
void reserve(std::size_t n)
{
// Get current stream positions as offsets.
std::size_t gnext = gptr() - &buffer_[0];
std::size_t gend = egptr() - &buffer_[0];
std::size_t pnext = pptr() - &buffer_[0];
std::size_t pend = epptr() - &buffer_[0];
// Check if there is already enough space in the put area.
if (n <= pend - pnext)
{
return;
}
// Shift existing contents of get area to start of buffer.
if (gnext > 0)
{
std::rotate(&buffer_[0], &buffer_[0] + gnext, &buffer_[0] + pend);
gend -= gnext;
pnext -= gnext;
}
// Ensure buffer is large enough to hold at least the specified size.
if (n > pend - pnext)
{
if (n <= max_size_ && pnext <= max_size_ - n)
{
buffer_.resize((std::max<std::size_t>)(pnext + n, 1));
}
else
{
throw std::length_error("asio::streambuf too long");
}
}
// Update stream positions.
setg(&buffer_[0], &buffer_[0], &buffer_[0] + gend);
setp(&buffer_[0] + pnext, &buffer_[0] + pnext + n);
}
private:
std::size_t max_size_;
std::vector<char_type, Allocator> buffer_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_STREAMBUF_HPP

View file

@ -0,0 +1,790 @@
//
// buffer.hpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFER_HPP
#define ASIO_BUFFER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include <boost/array.hpp>
#include <boost/type_traits/is_const.hpp>
#include <string>
#include <vector>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_MSVC)
# if defined(_HAS_ITERATOR_DEBUGGING)
# if !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
# define ASIO_ENABLE_BUFFER_DEBUGGING
# endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
# endif // defined(_HAS_ITERATOR_DEBUGGING)
#endif // defined(BOOST_MSVC)
#if defined(__GNUC__)
# if defined(_GLIBCXX_DEBUG)
# if !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
# define ASIO_ENABLE_BUFFER_DEBUGGING
# endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
# endif // defined(_GLIBCXX_DEBUG)
#endif // defined(__GNUC__)
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
# include "asio/detail/push_options.hpp"
# include <boost/function.hpp>
# include "asio/detail/pop_options.hpp"
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
namespace asio {
class mutable_buffer;
class const_buffer;
namespace detail {
void* buffer_cast_helper(const mutable_buffer&);
const void* buffer_cast_helper(const const_buffer&);
std::size_t buffer_size_helper(const mutable_buffer&);
std::size_t buffer_size_helper(const const_buffer&);
} // namespace detail
/// Holds a buffer that can be modified.
/**
* The mutable_buffer class provides a safe representation of a buffer that can
* be modified. It does not own the underlying data, and so is cheap to copy or
* assign.
*/
class mutable_buffer
{
public:
/// Construct an empty buffer.
mutable_buffer()
: data_(0),
size_(0)
{
}
/// Construct a buffer to represent a given memory range.
mutable_buffer(void* data, std::size_t size)
: data_(data),
size_(size)
{
}
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
mutable_buffer(void* data, std::size_t size,
boost::function<void()> debug_check)
: data_(data),
size_(size),
debug_check_(debug_check)
{
}
const boost::function<void()>& get_debug_check() const
{
return debug_check_;
}
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
private:
friend void* asio::detail::buffer_cast_helper(
const mutable_buffer& b);
friend std::size_t asio::detail::buffer_size_helper(
const mutable_buffer& b);
void* data_;
std::size_t size_;
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
boost::function<void()> debug_check_;
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
};
namespace detail {
inline void* buffer_cast_helper(const mutable_buffer& b)
{
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
if (b.size_ && b.debug_check_)
b.debug_check_();
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
return b.data_;
}
inline std::size_t buffer_size_helper(const mutable_buffer& b)
{
return b.size_;
}
} // namespace detail
/// Cast a non-modifiable buffer to a specified pointer to POD type.
/**
* @relates mutable_buffer
*/
template <typename PointerToPodType>
inline PointerToPodType buffer_cast(const mutable_buffer& b)
{
return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
}
/// Get the number of bytes in a non-modifiable buffer.
/**
* @relates mutable_buffer
*/
inline std::size_t buffer_size(const mutable_buffer& b)
{
return detail::buffer_size_helper(b);
}
/// Create a new modifiable buffer that is offset from the start of another.
/**
* @relates mutable_buffer
*/
inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start)
{
if (start > buffer_size(b))
return mutable_buffer();
char* new_data = buffer_cast<char*>(b) + start;
std::size_t new_size = buffer_size(b) - start;
return mutable_buffer(new_data, new_size
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, b.get_debug_check()
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
);
}
/// Create a new modifiable buffer that is offset from the start of another.
/**
* @relates mutable_buffer
*/
inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b)
{
if (start > buffer_size(b))
return mutable_buffer();
char* new_data = buffer_cast<char*>(b) + start;
std::size_t new_size = buffer_size(b) - start;
return mutable_buffer(new_data, new_size
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, b.get_debug_check()
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
);
}
/// Adapts a single modifiable buffer so that it meets the requirements of the
/// MutableBufferSequence concept.
class mutable_buffers_1
: public mutable_buffer
{
public:
/// The type for each element in the list of buffers.
typedef mutable_buffer value_type;
/// A random-access iterator type that may be used to read elements.
typedef const mutable_buffer* const_iterator;
/// Construct to represent a single modifiable buffer.
explicit mutable_buffers_1(const mutable_buffer& b)
: mutable_buffer(b)
{
}
/// Get a random-access iterator to the first element.
const_iterator begin() const
{
return this;
}
/// Get a random-access iterator for one past the last element.
const_iterator end() const
{
return begin() + 1;
}
};
/// Holds a buffer that cannot be modified.
/**
* The const_buffer class provides a safe representation of a buffer that cannot
* be modified. It does not own the underlying data, and so is cheap to copy or
* assign.
*/
class const_buffer
{
public:
/// Construct an empty buffer.
const_buffer()
: data_(0),
size_(0)
{
}
/// Construct a buffer to represent a given memory range.
const_buffer(const void* data, std::size_t size)
: data_(data),
size_(size)
{
}
/// Construct a non-modifiable buffer from a modifiable one.
const_buffer(const mutable_buffer& b)
: data_(asio::detail::buffer_cast_helper(b)),
size_(asio::detail::buffer_size_helper(b))
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, debug_check_(b.get_debug_check())
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
{
}
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
const_buffer(const void* data, std::size_t size,
boost::function<void()> debug_check)
: data_(data),
size_(size),
debug_check_(debug_check)
{
}
const boost::function<void()>& get_debug_check() const
{
return debug_check_;
}
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
private:
friend const void* asio::detail::buffer_cast_helper(
const const_buffer& b);
friend std::size_t asio::detail::buffer_size_helper(
const const_buffer& b);
const void* data_;
std::size_t size_;
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
boost::function<void()> debug_check_;
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
};
namespace detail {
inline const void* buffer_cast_helper(const const_buffer& b)
{
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
if (b.size_ && b.debug_check_)
b.debug_check_();
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
return b.data_;
}
inline std::size_t buffer_size_helper(const const_buffer& b)
{
return b.size_;
}
} // namespace detail
/// Cast a non-modifiable buffer to a specified pointer to POD type.
/**
* @relates const_buffer
*/
template <typename PointerToPodType>
inline PointerToPodType buffer_cast(const const_buffer& b)
{
return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
}
/// Get the number of bytes in a non-modifiable buffer.
/**
* @relates const_buffer
*/
inline std::size_t buffer_size(const const_buffer& b)
{
return detail::buffer_size_helper(b);
}
/// Create a new non-modifiable buffer that is offset from the start of another.
/**
* @relates const_buffer
*/
inline const_buffer operator+(const const_buffer& b, std::size_t start)
{
if (start > buffer_size(b))
return const_buffer();
const char* new_data = buffer_cast<const char*>(b) + start;
std::size_t new_size = buffer_size(b) - start;
return const_buffer(new_data, new_size
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, b.get_debug_check()
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
);
}
/// Create a new non-modifiable buffer that is offset from the start of another.
/**
* @relates const_buffer
*/
inline const_buffer operator+(std::size_t start, const const_buffer& b)
{
if (start > buffer_size(b))
return const_buffer();
const char* new_data = buffer_cast<const char*>(b) + start;
std::size_t new_size = buffer_size(b) - start;
return const_buffer(new_data, new_size
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, b.get_debug_check()
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
);
}
/// Adapts a single non-modifiable buffer so that it meets the requirements of
/// the ConstBufferSequence concept.
class const_buffers_1
: public const_buffer
{
public:
/// The type for each element in the list of buffers.
typedef const_buffer value_type;
/// A random-access iterator type that may be used to read elements.
typedef const const_buffer* const_iterator;
/// Construct to represent a single non-modifiable buffer.
explicit const_buffers_1(const const_buffer& b)
: const_buffer(b)
{
}
/// Get a random-access iterator to the first element.
const_iterator begin() const
{
return this;
}
/// Get a random-access iterator for one past the last element.
const_iterator end() const
{
return begin() + 1;
}
};
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
namespace detail {
template <typename Iterator>
class buffer_debug_check
{
public:
buffer_debug_check(Iterator iter)
: iter_(iter)
{
}
void operator()()
{
*iter_;
}
private:
Iterator iter_;
};
} // namespace detail
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
/** @defgroup buffer asio::buffer
*
* @brief The asio::buffer function is used to create a buffer object to
* represent raw memory, an array of POD elements, or a vector of POD elements.
*
* The simplest use case involves reading or writing a single buffer of a
* specified size:
*
* @code sock.write(asio::buffer(data, size)); @endcode
*
* In the above example, the return value of asio::buffer meets the
* requirements of the ConstBufferSequence concept so that it may be directly
* passed to the socket's write function. A buffer created for modifiable
* memory also meets the requirements of the MutableBufferSequence concept.
*
* An individual buffer may be created from a builtin array, std::vector or
* boost::array of POD elements. This helps prevent buffer overruns by
* automatically determining the size of the buffer:
*
* @code char d1[128];
* size_t bytes_transferred = sock.read(asio::buffer(d1));
*
* std::vector<char> d2(128);
* bytes_transferred = sock.read(asio::buffer(d2));
*
* boost::array<char, 128> d3;
* bytes_transferred = sock.read(asio::buffer(d3)); @endcode
*
* To read or write using multiple buffers (i.e. scatter-gather I/O), multiple
* buffer objects may be assigned into a container that supports the
* MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts:
*
* @code
* char d1[128];
* std::vector<char> d2(128);
* boost::array<char, 128> d3;
*
* boost::array<mutable_buffer, 3> bufs1 = {
* asio::buffer(d1),
* asio::buffer(d2),
* asio::buffer(d3) };
* bytes_transferred = sock.read(bufs1);
*
* std::vector<const_buffer> bufs2;
* bufs2.push_back(asio::buffer(d1));
* bufs2.push_back(asio::buffer(d2));
* bufs2.push_back(asio::buffer(d3));
* bytes_transferred = sock.write(bufs2); @endcode
*/
/*@{*/
/// Create a new modifiable buffer from an existing buffer.
inline mutable_buffers_1 buffer(const mutable_buffer& b)
{
return mutable_buffers_1(b);
}
/// Create a new modifiable buffer from an existing buffer.
inline mutable_buffers_1 buffer(const mutable_buffer& b,
std::size_t max_size_in_bytes)
{
return mutable_buffers_1(
mutable_buffer(buffer_cast<void*>(b),
buffer_size(b) < max_size_in_bytes
? buffer_size(b) : max_size_in_bytes
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, b.get_debug_check()
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
));
}
/// Create a new non-modifiable buffer from an existing buffer.
inline const_buffers_1 buffer(const const_buffer& b)
{
return const_buffers_1(b);
}
/// Create a new non-modifiable buffer from an existing buffer.
inline const_buffers_1 buffer(const const_buffer& b,
std::size_t max_size_in_bytes)
{
return const_buffers_1(
const_buffer(buffer_cast<const void*>(b),
buffer_size(b) < max_size_in_bytes
? buffer_size(b) : max_size_in_bytes
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, b.get_debug_check()
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
));
}
/// Create a new modifiable buffer that represents the given memory range.
inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes)
{
return mutable_buffers_1(mutable_buffer(data, size_in_bytes));
}
/// Create a new non-modifiable buffer that represents the given memory range.
inline const_buffers_1 buffer(const void* data,
std::size_t size_in_bytes)
{
return const_buffers_1(const_buffer(data, size_in_bytes));
}
/// Create a new modifiable buffer that represents the given POD array.
template <typename PodType, std::size_t N>
inline mutable_buffers_1 buffer(PodType (&data)[N])
{
return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType)));
}
/// Create a new modifiable buffer that represents the given POD array.
template <typename PodType, std::size_t N>
inline mutable_buffers_1 buffer(PodType (&data)[N],
std::size_t max_size_in_bytes)
{
return mutable_buffers_1(
mutable_buffer(data,
N * sizeof(PodType) < max_size_in_bytes
? N * sizeof(PodType) : max_size_in_bytes));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename PodType, std::size_t N>
inline const_buffers_1 buffer(const PodType (&data)[N])
{
return const_buffers_1(const_buffer(data, N * sizeof(PodType)));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename PodType, std::size_t N>
inline const_buffers_1 buffer(const PodType (&data)[N],
std::size_t max_size_in_bytes)
{
return const_buffers_1(
const_buffer(data,
N * sizeof(PodType) < max_size_in_bytes
? N * sizeof(PodType) : max_size_in_bytes));
}
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
// Borland C++ thinks the overloads:
//
// unspecified buffer(boost::array<PodType, N>& array ...);
//
// and
//
// unspecified buffer(boost::array<const PodType, N>& array ...);
//
// are ambiguous. This will be worked around by using a buffer_types traits
// class that contains typedefs for the appropriate buffer and container
// classes, based on whether PodType is const or non-const.
namespace detail {
template <bool IsConst>
struct buffer_types_base;
template <>
struct buffer_types_base<false>
{
typedef mutable_buffer buffer_type;
typedef mutable_buffers_1 container_type;
};
template <>
struct buffer_types_base<true>
{
typedef const_buffer buffer_type;
typedef const_buffers_1 container_type;
};
template <typename PodType>
struct buffer_types
: public buffer_types_base<boost::is_const<PodType>::value>
{
};
} // namespace detail
template <typename PodType, std::size_t N>
inline typename detail::buffer_types<PodType>::container_type
buffer(boost::array<PodType, N>& data)
{
typedef typename asio::detail::buffer_types<PodType>::buffer_type
buffer_type;
typedef typename asio::detail::buffer_types<PodType>::container_type
container_type;
return container_type(
buffer_type(data.c_array(), data.size() * sizeof(PodType)));
}
template <typename PodType, std::size_t N>
inline typename detail::buffer_types<PodType>::container_type
buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes)
{
typedef typename asio::detail::buffer_types<PodType>::buffer_type
buffer_type;
typedef typename asio::detail::buffer_types<PodType>::container_type
container_type;
return container_type(
buffer_type(data.c_array(),
data.size() * sizeof(PodType) < max_size_in_bytes
? data.size() * sizeof(PodType) : max_size_in_bytes));
}
#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
/// Create a new modifiable buffer that represents the given POD array.
template <typename PodType, std::size_t N>
inline mutable_buffers_1 buffer(boost::array<PodType, N>& data)
{
return mutable_buffers_1(
mutable_buffer(data.c_array(), data.size() * sizeof(PodType)));
}
/// Create a new modifiable buffer that represents the given POD array.
template <typename PodType, std::size_t N>
inline mutable_buffers_1 buffer(boost::array<PodType, N>& data,
std::size_t max_size_in_bytes)
{
return mutable_buffers_1(
mutable_buffer(data.c_array(),
data.size() * sizeof(PodType) < max_size_in_bytes
? data.size() * sizeof(PodType) : max_size_in_bytes));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename PodType, std::size_t N>
inline const_buffers_1 buffer(boost::array<const PodType, N>& data)
{
return const_buffers_1(
const_buffer(data.data(), data.size() * sizeof(PodType)));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename PodType, std::size_t N>
inline const_buffers_1 buffer(boost::array<const PodType, N>& data,
std::size_t max_size_in_bytes)
{
return const_buffers_1(
const_buffer(data.data(),
data.size() * sizeof(PodType) < max_size_in_bytes
? data.size() * sizeof(PodType) : max_size_in_bytes));
}
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename PodType, std::size_t N>
inline const_buffers_1 buffer(const boost::array<PodType, N>& data)
{
return const_buffers_1(
const_buffer(data.data(), data.size() * sizeof(PodType)));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename PodType, std::size_t N>
inline const_buffers_1 buffer(const boost::array<PodType, N>& data,
std::size_t max_size_in_bytes)
{
return const_buffers_1(
const_buffer(data.data(),
data.size() * sizeof(PodType) < max_size_in_bytes
? data.size() * sizeof(PodType) : max_size_in_bytes));
}
/// Create a new modifiable buffer that represents the given POD vector.
/**
* @note The buffer is invalidated by any vector operation that would also
* invalidate iterators.
*/
template <typename PodType, typename Allocator>
inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data)
{
return mutable_buffers_1(
mutable_buffer(&data[0], data.size() * sizeof(PodType)
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, detail::buffer_debug_check<
typename std::vector<PodType, Allocator>::iterator
>(data.begin())
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
));
}
/// Create a new modifiable buffer that represents the given POD vector.
/**
* @note The buffer is invalidated by any vector operation that would also
* invalidate iterators.
*/
template <typename PodType, typename Allocator>
inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data,
std::size_t max_size_in_bytes)
{
return mutable_buffers_1(
mutable_buffer(&data[0],
data.size() * sizeof(PodType) < max_size_in_bytes
? data.size() * sizeof(PodType) : max_size_in_bytes
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, detail::buffer_debug_check<
typename std::vector<PodType, Allocator>::iterator
>(data.begin())
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
));
}
/// Create a new non-modifiable buffer that represents the given POD vector.
/**
* @note The buffer is invalidated by any vector operation that would also
* invalidate iterators.
*/
template <typename PodType, typename Allocator>
inline const_buffers_1 buffer(
const std::vector<PodType, Allocator>& data)
{
return const_buffers_1(
const_buffer(&data[0], data.size() * sizeof(PodType)
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, detail::buffer_debug_check<
typename std::vector<PodType, Allocator>::const_iterator
>(data.begin())
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
));
}
/// Create a new non-modifiable buffer that represents the given POD vector.
/**
* @note The buffer is invalidated by any vector operation that would also
* invalidate iterators.
*/
template <typename PodType, typename Allocator>
inline const_buffers_1 buffer(
const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes)
{
return const_buffers_1(
const_buffer(&data[0],
data.size() * sizeof(PodType) < max_size_in_bytes
? data.size() * sizeof(PodType) : max_size_in_bytes
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, detail::buffer_debug_check<
typename std::vector<PodType, Allocator>::const_iterator
>(data.begin())
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
));
}
/// Create a new non-modifiable buffer that represents the given string.
/**
* @note The buffer is invalidated by any non-const operation called on the
* given string object.
*/
inline const_buffers_1 buffer(const std::string& data)
{
return const_buffers_1(const_buffer(data.data(), data.size()
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, detail::buffer_debug_check<std::string::const_iterator>(data.begin())
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
));
}
/// Create a new non-modifiable buffer that represents the given string.
/**
* @note The buffer is invalidated by any non-const operation called on the
* given string object.
*/
inline const_buffers_1 buffer(const std::string& data,
std::size_t max_size_in_bytes)
{
return const_buffers_1(
const_buffer(data.data(),
data.size() < max_size_in_bytes
? data.size() : max_size_in_bytes
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
, detail::buffer_debug_check<std::string::const_iterator>(data.begin())
#endif // ASIO_ENABLE_BUFFER_DEBUGGING
));
}
/*@}*/
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFER_HPP

View file

@ -0,0 +1,407 @@
//
// buffered_read_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFERED_READ_STREAM_HPP
#define ASIO_BUFFERED_READ_STREAM_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <cstring>
#include <boost/config.hpp>
#include <boost/type_traits.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/buffered_read_stream_fwd.hpp"
#include "asio/buffer.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/buffer_resize_guard.hpp"
#include "asio/detail/buffered_stream_storage.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
/// Adds buffering to the read-related operations of a stream.
/**
* The buffered_read_stream class template can be used to add buffering to the
* synchronous and asynchronous read operations of a stream.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* AsyncReadStream, AsyncWriteStream, Stream, Sync_Read_Stream, SyncWriteStream.
*/
template <typename Stream>
class buffered_read_stream
: private noncopyable
{
public:
/// The type of the next layer.
typedef typename boost::remove_reference<Stream>::type next_layer_type;
/// The type of the lowest layer.
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
#if defined(GENERATING_DOCUMENTATION)
/// The default buffer size.
static const std::size_t default_buffer_size = implementation_defined;
#else
BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024);
#endif
/// Construct, passing the specified argument to initialise the next layer.
template <typename Arg>
explicit buffered_read_stream(Arg& a)
: next_layer_(a),
storage_(default_buffer_size)
{
}
/// Construct, passing the specified argument to initialise the next layer.
template <typename Arg>
buffered_read_stream(Arg& a, std::size_t buffer_size)
: next_layer_(a),
storage_(buffer_size)
{
}
/// Get a reference to the next layer.
next_layer_type& next_layer()
{
return next_layer_;
}
/// Get a reference to the lowest layer.
lowest_layer_type& lowest_layer()
{
return next_layer_.lowest_layer();
}
/// Get the io_service associated with the object.
asio::io_service& io_service()
{
return next_layer_.io_service();
}
/// Close the stream.
void close()
{
next_layer_.close();
}
/// Close the stream.
asio::error_code close(asio::error_code& ec)
{
return next_layer_.close(ec);
}
/// Write the given data to the stream. Returns the number of bytes written.
/// Throws an exception on failure.
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers)
{
return next_layer_.write_some(buffers);
}
/// Write the given data to the stream. Returns the number of bytes written,
/// or 0 if an error occurred.
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers,
asio::error_code& ec)
{
return next_layer_.write_some(buffers, ec);
}
/// Start an asynchronous write. The data being written must be valid for the
/// lifetime of the asynchronous operation.
template <typename ConstBufferSequence, typename WriteHandler>
void async_write_some(const ConstBufferSequence& buffers,
WriteHandler handler)
{
next_layer_.async_write_some(buffers, handler);
}
/// Fill the buffer with some data. Returns the number of bytes placed in the
/// buffer as a result of the operation. Throws an exception on failure.
std::size_t fill()
{
detail::buffer_resize_guard<detail::buffered_stream_storage>
resize_guard(storage_);
std::size_t previous_size = storage_.size();
storage_.resize(storage_.capacity());
storage_.resize(previous_size + next_layer_.read_some(buffer(
storage_.data() + previous_size,
storage_.size() - previous_size)));
resize_guard.commit();
return storage_.size() - previous_size;
}
/// Fill the buffer with some data. Returns the number of bytes placed in the
/// buffer as a result of the operation, or 0 if an error occurred.
std::size_t fill(asio::error_code& ec)
{
detail::buffer_resize_guard<detail::buffered_stream_storage>
resize_guard(storage_);
std::size_t previous_size = storage_.size();
storage_.resize(storage_.capacity());
storage_.resize(previous_size + next_layer_.read_some(buffer(
storage_.data() + previous_size,
storage_.size() - previous_size),
ec));
resize_guard.commit();
return storage_.size() - previous_size;
}
template <typename ReadHandler>
class fill_handler
{
public:
fill_handler(asio::io_service& io_service,
detail::buffered_stream_storage& storage,
std::size_t previous_size, ReadHandler handler)
: io_service_(io_service),
storage_(storage),
previous_size_(previous_size),
handler_(handler)
{
}
void operator()(const asio::error_code& ec,
std::size_t bytes_transferred)
{
storage_.resize(previous_size_ + bytes_transferred);
io_service_.dispatch(detail::bind_handler(
handler_, ec, bytes_transferred));
}
private:
asio::io_service& io_service_;
detail::buffered_stream_storage& storage_;
std::size_t previous_size_;
ReadHandler handler_;
};
/// Start an asynchronous fill.
template <typename ReadHandler>
void async_fill(ReadHandler handler)
{
std::size_t previous_size = storage_.size();
storage_.resize(storage_.capacity());
next_layer_.async_read_some(
buffer(
storage_.data() + previous_size,
storage_.size() - previous_size),
fill_handler<ReadHandler>(io_service(),
storage_, previous_size, handler));
}
/// Read some data from the stream. Returns the number of bytes read. Throws
/// an exception on failure.
template <typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence& buffers)
{
if (storage_.empty())
fill();
return copy(buffers);
}
/// Read some data from the stream. Returns the number of bytes read or 0 if
/// an error occurred.
template <typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence& buffers,
asio::error_code& ec)
{
ec = asio::error_code();
if (storage_.empty() && !fill(ec))
return 0;
return copy(buffers);
}
template <typename MutableBufferSequence, typename ReadHandler>
class read_some_handler
{
public:
read_some_handler(asio::io_service& io_service,
detail::buffered_stream_storage& storage,
const MutableBufferSequence& buffers, ReadHandler handler)
: io_service_(io_service),
storage_(storage),
buffers_(buffers),
handler_(handler)
{
}
void operator()(const asio::error_code& ec, std::size_t)
{
if (ec || storage_.empty())
{
std::size_t length = 0;
io_service_.dispatch(detail::bind_handler(handler_, ec, length));
}
else
{
using namespace std; // For memcpy.
std::size_t bytes_avail = storage_.size();
std::size_t bytes_copied = 0;
typename MutableBufferSequence::const_iterator iter = buffers_.begin();
typename MutableBufferSequence::const_iterator end = buffers_.end();
for (; iter != end && bytes_avail > 0; ++iter)
{
std::size_t max_length = buffer_size(*iter);
std::size_t length = (max_length < bytes_avail)
? max_length : bytes_avail;
memcpy(buffer_cast<void*>(*iter),
storage_.data() + bytes_copied, length);
bytes_copied += length;
bytes_avail -= length;
}
storage_.consume(bytes_copied);
io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied));
}
}
private:
asio::io_service& io_service_;
detail::buffered_stream_storage& storage_;
MutableBufferSequence buffers_;
ReadHandler handler_;
};
/// Start an asynchronous read. The buffer into which the data will be read
/// must be valid for the lifetime of the asynchronous operation.
template <typename MutableBufferSequence, typename ReadHandler>
void async_read_some(const MutableBufferSequence& buffers,
ReadHandler handler)
{
if (storage_.empty())
{
async_fill(read_some_handler<MutableBufferSequence, ReadHandler>(
io_service(), storage_, buffers, handler));
}
else
{
std::size_t length = copy(buffers);
io_service().post(detail::bind_handler(
handler, asio::error_code(), length));
}
}
/// Peek at the incoming data on the stream. Returns the number of bytes read.
/// Throws an exception on failure.
template <typename MutableBufferSequence>
std::size_t peek(const MutableBufferSequence& buffers)
{
if (storage_.empty())
fill();
return peek_copy(buffers);
}
/// Peek at the incoming data on the stream. Returns the number of bytes read,
/// or 0 if an error occurred.
template <typename MutableBufferSequence>
std::size_t peek(const MutableBufferSequence& buffers,
asio::error_code& ec)
{
ec = asio::error_code();
if (storage_.empty() && !fill(ec))
return 0;
return peek_copy(buffers);
}
/// Determine the amount of data that may be read without blocking.
std::size_t in_avail()
{
return storage_.size();
}
/// Determine the amount of data that may be read without blocking.
std::size_t in_avail(asio::error_code& ec)
{
ec = asio::error_code();
return storage_.size();
}
private:
/// Copy data out of the internal buffer to the specified target buffer.
/// Returns the number of bytes copied.
template <typename MutableBufferSequence>
std::size_t copy(const MutableBufferSequence& buffers)
{
using namespace std; // For memcpy.
std::size_t bytes_avail = storage_.size();
std::size_t bytes_copied = 0;
typename MutableBufferSequence::const_iterator iter = buffers.begin();
typename MutableBufferSequence::const_iterator end = buffers.end();
for (; iter != end && bytes_avail > 0; ++iter)
{
std::size_t max_length = buffer_size(*iter);
std::size_t length = (max_length < bytes_avail)
? max_length : bytes_avail;
memcpy(buffer_cast<void*>(*iter), storage_.data() + bytes_copied, length);
bytes_copied += length;
bytes_avail -= length;
}
storage_.consume(bytes_copied);
return bytes_copied;
}
/// Copy data from the internal buffer to the specified target buffer, without
/// removing the data from the internal buffer. Returns the number of bytes
/// copied.
template <typename MutableBufferSequence>
std::size_t peek_copy(const MutableBufferSequence& buffers)
{
using namespace std; // For memcpy.
std::size_t bytes_avail = storage_.size();
std::size_t bytes_copied = 0;
typename MutableBufferSequence::const_iterator iter = buffers.begin();
typename MutableBufferSequence::const_iterator end = buffers.end();
for (; iter != end && bytes_avail > 0; ++iter)
{
std::size_t max_length = buffer_size(*iter);
std::size_t length = (max_length < bytes_avail)
? max_length : bytes_avail;
memcpy(buffer_cast<void*>(*iter), storage_.data() + bytes_copied, length);
bytes_copied += length;
bytes_avail -= length;
}
return bytes_copied;
}
/// The next layer.
Stream next_layer_;
// The data in the buffer.
detail::buffered_stream_storage storage_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFERED_READ_STREAM_HPP

View file

@ -0,0 +1,29 @@
//
// buffered_read_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFERED_READ_STREAM_FWD_HPP
#define ASIO_BUFFERED_READ_STREAM_FWD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename Stream>
class buffered_read_stream;
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFERED_READ_STREAM_FWD_HPP

View file

@ -0,0 +1,243 @@
//
// buffered_stream.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFERED_STREAM_HPP
#define ASIO_BUFFERED_STREAM_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/buffered_read_stream.hpp"
#include "asio/buffered_write_stream.hpp"
#include "asio/buffered_stream_fwd.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
/// Adds buffering to the read- and write-related operations of a stream.
/**
* The buffered_stream class template can be used to add buffering to the
* synchronous and asynchronous read and write operations of a stream.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
*/
template <typename Stream>
class buffered_stream
: private noncopyable
{
public:
/// The type of the next layer.
typedef typename boost::remove_reference<Stream>::type next_layer_type;
/// The type of the lowest layer.
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
/// Construct, passing the specified argument to initialise the next layer.
template <typename Arg>
explicit buffered_stream(Arg& a)
: inner_stream_impl_(a),
stream_impl_(inner_stream_impl_)
{
}
/// Construct, passing the specified argument to initialise the next layer.
template <typename Arg>
explicit buffered_stream(Arg& a, std::size_t read_buffer_size,
std::size_t write_buffer_size)
: inner_stream_impl_(a, write_buffer_size),
stream_impl_(inner_stream_impl_, read_buffer_size)
{
}
/// Get a reference to the next layer.
next_layer_type& next_layer()
{
return stream_impl_.next_layer().next_layer();
}
/// Get a reference to the lowest layer.
lowest_layer_type& lowest_layer()
{
return stream_impl_.lowest_layer();
}
/// Get the io_service associated with the object.
asio::io_service& io_service()
{
return stream_impl_.io_service();
}
/// Close the stream.
void close()
{
stream_impl_.close();
}
/// Close the stream.
asio::error_code close(asio::error_code& ec)
{
return stream_impl_.close(ec);
}
/// Flush all data from the buffer to the next layer. Returns the number of
/// bytes written to the next layer on the last write operation. Throws an
/// exception on failure.
std::size_t flush()
{
return stream_impl_.next_layer().flush();
}
/// Flush all data from the buffer to the next layer. Returns the number of
/// bytes written to the next layer on the last write operation, or 0 if an
/// error occurred.
std::size_t flush(asio::error_code& ec)
{
return stream_impl_.next_layer().flush(ec);
}
/// Start an asynchronous flush.
template <typename WriteHandler>
void async_flush(WriteHandler handler)
{
return stream_impl_.next_layer().async_flush(handler);
}
/// Write the given data to the stream. Returns the number of bytes written.
/// Throws an exception on failure.
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers)
{
return stream_impl_.write_some(buffers);
}
/// Write the given data to the stream. Returns the number of bytes written,
/// or 0 if an error occurred.
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers,
asio::error_code& ec)
{
return stream_impl_.write_some(buffers, ec);
}
/// Start an asynchronous write. The data being written must be valid for the
/// lifetime of the asynchronous operation.
template <typename ConstBufferSequence, typename WriteHandler>
void async_write_some(const ConstBufferSequence& buffers,
WriteHandler handler)
{
stream_impl_.async_write_some(buffers, handler);
}
/// Fill the buffer with some data. Returns the number of bytes placed in the
/// buffer as a result of the operation. Throws an exception on failure.
std::size_t fill()
{
return stream_impl_.fill();
}
/// Fill the buffer with some data. Returns the number of bytes placed in the
/// buffer as a result of the operation, or 0 if an error occurred.
std::size_t fill(asio::error_code& ec)
{
return stream_impl_.fill(ec);
}
/// Start an asynchronous fill.
template <typename ReadHandler>
void async_fill(ReadHandler handler)
{
stream_impl_.async_fill(handler);
}
/// Read some data from the stream. Returns the number of bytes read. Throws
/// an exception on failure.
template <typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence& buffers)
{
return stream_impl_.read_some(buffers);
}
/// Read some data from the stream. Returns the number of bytes read or 0 if
/// an error occurred.
template <typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence& buffers,
asio::error_code& ec)
{
return stream_impl_.read_some(buffers, ec);
}
/// Start an asynchronous read. The buffer into which the data will be read
/// must be valid for the lifetime of the asynchronous operation.
template <typename MutableBufferSequence, typename ReadHandler>
void async_read_some(const MutableBufferSequence& buffers,
ReadHandler handler)
{
stream_impl_.async_read_some(buffers, handler);
}
/// Peek at the incoming data on the stream. Returns the number of bytes read.
/// Throws an exception on failure.
template <typename MutableBufferSequence>
std::size_t peek(const MutableBufferSequence& buffers)
{
return stream_impl_.peek(buffers);
}
/// Peek at the incoming data on the stream. Returns the number of bytes read,
/// or 0 if an error occurred.
template <typename MutableBufferSequence>
std::size_t peek(const MutableBufferSequence& buffers,
asio::error_code& ec)
{
return stream_impl_.peek(buffers, ec);
}
/// Determine the amount of data that may be read without blocking.
std::size_t in_avail()
{
return stream_impl_.in_avail();
}
/// Determine the amount of data that may be read without blocking.
std::size_t in_avail(asio::error_code& ec)
{
return stream_impl_.in_avail(ec);
}
private:
// The buffered write stream.
typedef buffered_write_stream<Stream> write_stream_type;
write_stream_type inner_stream_impl_;
// The buffered read stream.
typedef buffered_read_stream<write_stream_type&> read_stream_type;
read_stream_type stream_impl_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFERED_STREAM_HPP

View file

@ -0,0 +1,29 @@
//
// buffered_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFERED_STREAM_FWD_HPP
#define ASIO_BUFFERED_STREAM_FWD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename Stream>
class buffered_stream;
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFERED_STREAM_FWD_HPP

View file

@ -0,0 +1,361 @@
//
// buffered_write_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFERED_WRITE_STREAM_HPP
#define ASIO_BUFFERED_WRITE_STREAM_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <cstring>
#include <boost/config.hpp>
#include <boost/type_traits.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/buffered_write_stream_fwd.hpp"
#include "asio/buffer.hpp"
#include "asio/completion_condition.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/write.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/buffered_stream_storage.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
/// Adds buffering to the write-related operations of a stream.
/**
* The buffered_write_stream class template can be used to add buffering to the
* synchronous and asynchronous write operations of a stream.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
*/
template <typename Stream>
class buffered_write_stream
: private noncopyable
{
public:
/// The type of the next layer.
typedef typename boost::remove_reference<Stream>::type next_layer_type;
/// The type of the lowest layer.
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
#if defined(GENERATING_DOCUMENTATION)
/// The default buffer size.
static const std::size_t default_buffer_size = implementation_defined;
#else
BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024);
#endif
/// Construct, passing the specified argument to initialise the next layer.
template <typename Arg>
explicit buffered_write_stream(Arg& a)
: next_layer_(a),
storage_(default_buffer_size)
{
}
/// Construct, passing the specified argument to initialise the next layer.
template <typename Arg>
buffered_write_stream(Arg& a, std::size_t buffer_size)
: next_layer_(a),
storage_(buffer_size)
{
}
/// Get a reference to the next layer.
next_layer_type& next_layer()
{
return next_layer_;
}
/// Get a reference to the lowest layer.
lowest_layer_type& lowest_layer()
{
return next_layer_.lowest_layer();
}
/// Get the io_service associated with the object.
asio::io_service& io_service()
{
return next_layer_.io_service();
}
/// Close the stream.
void close()
{
next_layer_.close();
}
/// Close the stream.
asio::error_code close(asio::error_code& ec)
{
return next_layer_.close(ec);
}
/// Flush all data from the buffer to the next layer. Returns the number of
/// bytes written to the next layer on the last write operation. Throws an
/// exception on failure.
std::size_t flush()
{
std::size_t bytes_written = write(next_layer_,
buffer(storage_.data(), storage_.size()));
storage_.consume(bytes_written);
return bytes_written;
}
/// Flush all data from the buffer to the next layer. Returns the number of
/// bytes written to the next layer on the last write operation, or 0 if an
/// error occurred.
std::size_t flush(asio::error_code& ec)
{
std::size_t bytes_written = write(next_layer_,
buffer(storage_.data(), storage_.size()),
transfer_all(), ec);
storage_.consume(bytes_written);
return bytes_written;
}
template <typename WriteHandler>
class flush_handler
{
public:
flush_handler(asio::io_service& io_service,
detail::buffered_stream_storage& storage, WriteHandler handler)
: io_service_(io_service),
storage_(storage),
handler_(handler)
{
}
void operator()(const asio::error_code& ec,
std::size_t bytes_written)
{
storage_.consume(bytes_written);
io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_written));
}
private:
asio::io_service& io_service_;
detail::buffered_stream_storage& storage_;
WriteHandler handler_;
};
/// Start an asynchronous flush.
template <typename WriteHandler>
void async_flush(WriteHandler handler)
{
async_write(next_layer_, buffer(storage_.data(), storage_.size()),
flush_handler<WriteHandler>(io_service(), storage_, handler));
}
/// Write the given data to the stream. Returns the number of bytes written.
/// Throws an exception on failure.
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers)
{
if (storage_.size() == storage_.capacity())
flush();
return copy(buffers);
}
/// Write the given data to the stream. Returns the number of bytes written,
/// or 0 if an error occurred and the error handler did not throw.
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers,
asio::error_code& ec)
{
ec = asio::error_code();
if (storage_.size() == storage_.capacity() && !flush(ec))
return 0;
return copy(buffers);
}
template <typename ConstBufferSequence, typename WriteHandler>
class write_some_handler
{
public:
write_some_handler(asio::io_service& io_service,
detail::buffered_stream_storage& storage,
const ConstBufferSequence& buffers, WriteHandler handler)
: io_service_(io_service),
storage_(storage),
buffers_(buffers),
handler_(handler)
{
}
void operator()(const asio::error_code& ec, std::size_t)
{
if (ec)
{
std::size_t length = 0;
io_service_.dispatch(detail::bind_handler(handler_, ec, length));
}
else
{
using namespace std; // For memcpy.
std::size_t orig_size = storage_.size();
std::size_t space_avail = storage_.capacity() - orig_size;
std::size_t bytes_copied = 0;
typename ConstBufferSequence::const_iterator iter = buffers_.begin();
typename ConstBufferSequence::const_iterator end = buffers_.end();
for (; iter != end && space_avail > 0; ++iter)
{
std::size_t bytes_avail = buffer_size(*iter);
std::size_t length = (bytes_avail < space_avail)
? bytes_avail : space_avail;
storage_.resize(orig_size + bytes_copied + length);
memcpy(storage_.data() + orig_size + bytes_copied,
buffer_cast<const void*>(*iter), length);
bytes_copied += length;
space_avail -= length;
}
io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied));
}
}
private:
asio::io_service& io_service_;
detail::buffered_stream_storage& storage_;
ConstBufferSequence buffers_;
WriteHandler handler_;
};
/// Start an asynchronous write. The data being written must be valid for the
/// lifetime of the asynchronous operation.
template <typename ConstBufferSequence, typename WriteHandler>
void async_write_some(const ConstBufferSequence& buffers,
WriteHandler handler)
{
if (storage_.size() == storage_.capacity())
{
async_flush(write_some_handler<ConstBufferSequence, WriteHandler>(
io_service(), storage_, buffers, handler));
}
else
{
std::size_t bytes_copied = copy(buffers);
io_service().post(detail::bind_handler(
handler, asio::error_code(), bytes_copied));
}
}
/// Read some data from the stream. Returns the number of bytes read. Throws
/// an exception on failure.
template <typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence& buffers)
{
return next_layer_.read_some(buffers);
}
/// Read some data from the stream. Returns the number of bytes read or 0 if
/// an error occurred.
template <typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence& buffers,
asio::error_code& ec)
{
return next_layer_.read_some(buffers, ec);
}
/// Start an asynchronous read. The buffer into which the data will be read
/// must be valid for the lifetime of the asynchronous operation.
template <typename MutableBufferSequence, typename ReadHandler>
void async_read_some(const MutableBufferSequence& buffers,
ReadHandler handler)
{
next_layer_.async_read_some(buffers, handler);
}
/// Peek at the incoming data on the stream. Returns the number of bytes read.
/// Throws an exception on failure.
template <typename MutableBufferSequence>
std::size_t peek(const MutableBufferSequence& buffers)
{
return next_layer_.peek(buffers);
}
/// Peek at the incoming data on the stream. Returns the number of bytes read,
/// or 0 if an error occurred.
template <typename MutableBufferSequence>
std::size_t peek(const MutableBufferSequence& buffers,
asio::error_code& ec)
{
return next_layer_.peek(buffers, ec);
}
/// Determine the amount of data that may be read without blocking.
std::size_t in_avail()
{
return next_layer_.in_avail();
}
/// Determine the amount of data that may be read without blocking.
std::size_t in_avail(asio::error_code& ec)
{
return next_layer_.in_avail(ec);
}
private:
/// Copy data into the internal buffer from the specified source buffer.
/// Returns the number of bytes copied.
template <typename ConstBufferSequence>
std::size_t copy(const ConstBufferSequence& buffers)
{
using namespace std; // For memcpy.
std::size_t orig_size = storage_.size();
std::size_t space_avail = storage_.capacity() - orig_size;
std::size_t bytes_copied = 0;
typename ConstBufferSequence::const_iterator iter = buffers.begin();
typename ConstBufferSequence::const_iterator end = buffers.end();
for (; iter != end && space_avail > 0; ++iter)
{
std::size_t bytes_avail = buffer_size(*iter);
std::size_t length = (bytes_avail < space_avail)
? bytes_avail : space_avail;
storage_.resize(orig_size + bytes_copied + length);
memcpy(storage_.data() + orig_size + bytes_copied,
buffer_cast<const void*>(*iter), length);
bytes_copied += length;
space_avail -= length;
}
return bytes_copied;
}
/// The next layer.
Stream next_layer_;
// The data in the buffer.
detail::buffered_stream_storage storage_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFERED_WRITE_STREAM_HPP

View file

@ -0,0 +1,29 @@
//
// buffered_write_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
#define ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename Stream>
class buffered_write_stream;
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFERED_WRITE_STREAM_FWD_HPP

View file

@ -0,0 +1,101 @@
//
// completion_condition.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_COMPLETION_CONDITION_HPP
#define ASIO_COMPLETION_CONDITION_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
class transfer_all_t
{
public:
typedef bool result_type;
template <typename Error>
bool operator()(const Error& err, std::size_t)
{
return !!err;
}
};
class transfer_at_least_t
{
public:
typedef bool result_type;
explicit transfer_at_least_t(std::size_t minimum)
: minimum_(minimum)
{
}
template <typename Error>
bool operator()(const Error& err, std::size_t bytes_transferred)
{
return !!err || bytes_transferred >= minimum_;
}
private:
std::size_t minimum_;
};
} // namespace detail
/**
* @defgroup completion_condition Completion Condition Function Objects
*
* Function objects used for determining when a read or write operation should
* complete.
*/
/*@{*/
/// Return a completion condition function object that indicates that a read or
/// write operation should continue until all of the data has been transferred,
/// or until an error occurs.
#if defined(GENERATING_DOCUMENTATION)
unspecified transfer_all();
#else
inline detail::transfer_all_t transfer_all()
{
return detail::transfer_all_t();
}
#endif
/// Return a completion condition function object that indicates that a read or
/// write operation should continue until a minimum number of bytes has been
/// transferred, or until an error occurs.
#if defined(GENERATING_DOCUMENTATION)
unspecified transfer_at_least(std::size_t minimum);
#else
inline detail::transfer_at_least_t transfer_at_least(std::size_t minimum)
{
return detail::transfer_at_least_t(minimum);
}
#endif
/*@}*/
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_COMPLETION_CONDITION_HPP

View file

@ -0,0 +1,320 @@
//
// datagram_socket_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DATAGRAM_SOCKET_SERVICE_HPP
#define ASIO_DATAGRAM_SOCKET_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/epoll_reactor.hpp"
#include "asio/detail/kqueue_reactor.hpp"
#include "asio/detail/select_reactor.hpp"
#include "asio/detail/service_base.hpp"
#include "asio/detail/reactive_socket_service.hpp"
#include "asio/detail/win_iocp_socket_service.hpp"
namespace asio {
/// Default service implementation for a datagram socket.
template <typename Protocol>
class datagram_socket_service
#if defined(GENERATING_DOCUMENTATION)
: public asio::io_service::service
#else
: public asio::detail::service_base<datagram_socket_service<Protocol> >
#endif
{
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
static asio::io_service::id id;
#endif
/// The protocol type.
typedef Protocol protocol_type;
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
private:
// The type of the platform-specific implementation.
#if defined(ASIO_HAS_IOCP)
typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
#elif defined(ASIO_HAS_EPOLL)
typedef detail::reactive_socket_service<
Protocol, detail::epoll_reactor<false> > service_impl_type;
#elif defined(ASIO_HAS_KQUEUE)
typedef detail::reactive_socket_service<
Protocol, detail::kqueue_reactor<false> > service_impl_type;
#else
typedef detail::reactive_socket_service<
Protocol, detail::select_reactor<false> > service_impl_type;
#endif
public:
/// The type of a datagram socket.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined implementation_type;
#else
typedef typename service_impl_type::implementation_type implementation_type;
#endif
/// The native socket type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_type;
#else
typedef typename service_impl_type::native_type native_type;
#endif
/// Construct a new datagram socket service for the specified io_service.
explicit datagram_socket_service(asio::io_service& io_service)
: asio::detail::service_base<
datagram_socket_service<Protocol> >(io_service),
service_impl_(asio::use_service<service_impl_type>(io_service))
{
}
/// Destroy all user-defined handler objects owned by the service.
void shutdown_service()
{
}
/// Construct a new datagram socket implementation.
void construct(implementation_type& impl)
{
service_impl_.construct(impl);
}
/// Destroy a datagram socket implementation.
void destroy(implementation_type& impl)
{
service_impl_.destroy(impl);
}
// Open a new datagram socket implementation.
asio::error_code open(implementation_type& impl,
const protocol_type& protocol, asio::error_code& ec)
{
if (protocol.type() == SOCK_DGRAM)
service_impl_.open(impl, protocol, ec);
else
ec = asio::error::invalid_argument;
return ec;
}
/// Assign an existing native socket to a datagram socket.
asio::error_code assign(implementation_type& impl,
const protocol_type& protocol, const native_type& native_socket,
asio::error_code& ec)
{
return service_impl_.assign(impl, protocol, native_socket, ec);
}
/// Determine whether the socket is open.
bool is_open(const implementation_type& impl) const
{
return service_impl_.is_open(impl);
}
/// Close a datagram socket implementation.
asio::error_code close(implementation_type& impl,
asio::error_code& ec)
{
return service_impl_.close(impl, ec);
}
/// Get the native socket implementation.
native_type native(implementation_type& impl)
{
return service_impl_.native(impl);
}
/// Cancel all asynchronous operations associated with the socket.
asio::error_code cancel(implementation_type& impl,
asio::error_code& ec)
{
return service_impl_.cancel(impl, ec);
}
/// Determine whether the socket is at the out-of-band data mark.
bool at_mark(const implementation_type& impl,
asio::error_code& ec) const
{
return service_impl_.at_mark(impl, ec);
}
/// Determine the number of bytes available for reading.
std::size_t available(const implementation_type& impl,
asio::error_code& ec) const
{
return service_impl_.available(impl, ec);
}
// Bind the datagram socket to the specified local endpoint.
asio::error_code bind(implementation_type& impl,
const endpoint_type& endpoint, asio::error_code& ec)
{
return service_impl_.bind(impl, endpoint, ec);
}
/// Connect the datagram socket to the specified endpoint.
asio::error_code connect(implementation_type& impl,
const endpoint_type& peer_endpoint, asio::error_code& ec)
{
return service_impl_.connect(impl, peer_endpoint, ec);
}
/// Start an asynchronous connect.
template <typename ConnectHandler>
void async_connect(implementation_type& impl,
const endpoint_type& peer_endpoint, ConnectHandler handler)
{
service_impl_.async_connect(impl, peer_endpoint, handler);
}
/// Set a socket option.
template <typename SettableSocketOption>
asio::error_code set_option(implementation_type& impl,
const SettableSocketOption& option, asio::error_code& ec)
{
return service_impl_.set_option(impl, option, ec);
}
/// Get a socket option.
template <typename GettableSocketOption>
asio::error_code get_option(const implementation_type& impl,
GettableSocketOption& option, asio::error_code& ec) const
{
return service_impl_.get_option(impl, option, ec);
}
/// Perform an IO control command on the socket.
template <typename IoControlCommand>
asio::error_code io_control(implementation_type& impl,
IoControlCommand& command, asio::error_code& ec)
{
return service_impl_.io_control(impl, command, ec);
}
/// Get the local endpoint.
endpoint_type local_endpoint(const implementation_type& impl,
asio::error_code& ec) const
{
return service_impl_.local_endpoint(impl, ec);
}
/// Get the remote endpoint.
endpoint_type remote_endpoint(const implementation_type& impl,
asio::error_code& ec) const
{
return service_impl_.remote_endpoint(impl, ec);
}
/// Disable sends or receives on the socket.
asio::error_code shutdown(implementation_type& impl,
socket_base::shutdown_type what, asio::error_code& ec)
{
return service_impl_.shutdown(impl, what, ec);
}
/// Send the given data to the peer.
template <typename ConstBufferSequence>
std::size_t send(implementation_type& impl,
const ConstBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return service_impl_.send(impl, buffers, flags, ec);
}
/// Start an asynchronous send.
template <typename ConstBufferSequence, typename WriteHandler>
void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
socket_base::message_flags flags, WriteHandler handler)
{
service_impl_.async_send(impl, buffers, flags, handler);
}
/// Send a datagram to the specified endpoint.
template <typename ConstBufferSequence>
std::size_t send_to(implementation_type& impl,
const ConstBufferSequence& buffers, const endpoint_type& destination,
socket_base::message_flags flags, asio::error_code& ec)
{
return service_impl_.send_to(impl, buffers, destination, flags, ec);
}
/// Start an asynchronous send.
template <typename ConstBufferSequence, typename WriteHandler>
void async_send_to(implementation_type& impl,
const ConstBufferSequence& buffers, const endpoint_type& destination,
socket_base::message_flags flags, WriteHandler handler)
{
service_impl_.async_send_to(impl, buffers, destination, flags, handler);
}
/// Receive some data from the peer.
template <typename MutableBufferSequence>
std::size_t receive(implementation_type& impl,
const MutableBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return service_impl_.receive(impl, buffers, flags, ec);
}
/// Start an asynchronous receive.
template <typename MutableBufferSequence, typename ReadHandler>
void async_receive(implementation_type& impl,
const MutableBufferSequence& buffers,
socket_base::message_flags flags, ReadHandler handler)
{
service_impl_.async_receive(impl, buffers, flags, handler);
}
/// Receive a datagram with the endpoint of the sender.
template <typename MutableBufferSequence>
std::size_t receive_from(implementation_type& impl,
const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
socket_base::message_flags flags, asio::error_code& ec)
{
return service_impl_.receive_from(impl, buffers, sender_endpoint, flags,
ec);
}
/// Start an asynchronous receive that will get the endpoint of the sender.
template <typename MutableBufferSequence, typename ReadHandler>
void async_receive_from(implementation_type& impl,
const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
socket_base::message_flags flags, ReadHandler handler)
{
service_impl_.async_receive_from(impl, buffers, sender_endpoint, flags,
handler);
}
private:
// The service that provides the platform-specific implementation.
service_impl_type& service_impl_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DATAGRAM_SOCKET_SERVICE_HPP

View file

@ -0,0 +1,37 @@
//
// deadline_timer.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DEADLINE_TIMER_HPP
#define ASIO_DEADLINE_TIMER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/socket_types.hpp" // Must come before posix_time.
#include "asio/detail/push_options.hpp"
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_deadline_timer.hpp"
namespace asio {
/// Typedef for the typical usage of timer.
typedef basic_deadline_timer<boost::posix_time::ptime> deadline_timer;
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DEADLINE_TIMER_HPP

View file

@ -0,0 +1,164 @@
//
// deadline_timer_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DEADLINE_TIMER_SERVICE_HPP
#define ASIO_DEADLINE_TIMER_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/io_service.hpp"
#include "asio/time_traits.hpp"
#include "asio/detail/deadline_timer_service.hpp"
#include "asio/detail/epoll_reactor.hpp"
#include "asio/detail/kqueue_reactor.hpp"
#include "asio/detail/select_reactor.hpp"
#include "asio/detail/service_base.hpp"
namespace asio {
/// Default service implementation for a timer.
template <typename TimeType,
typename TimeTraits = asio::time_traits<TimeType> >
class deadline_timer_service
#if defined(GENERATING_DOCUMENTATION)
: public asio::io_service::service
#else
: public asio::detail::service_base<
deadline_timer_service<TimeType, TimeTraits> >
#endif
{
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
static asio::io_service::id id;
#endif
/// The time traits type.
typedef TimeTraits traits_type;
/// The time type.
typedef typename traits_type::time_type time_type;
/// The duration type.
typedef typename traits_type::duration_type duration_type;
private:
// The type of the platform-specific implementation.
#if defined(ASIO_HAS_IOCP)
typedef detail::deadline_timer_service<
traits_type, detail::select_reactor<true> > service_impl_type;
#elif defined(ASIO_HAS_EPOLL)
typedef detail::deadline_timer_service<
traits_type, detail::epoll_reactor<false> > service_impl_type;
#elif defined(ASIO_HAS_KQUEUE)
typedef detail::deadline_timer_service<
traits_type, detail::kqueue_reactor<false> > service_impl_type;
#else
typedef detail::deadline_timer_service<
traits_type, detail::select_reactor<false> > service_impl_type;
#endif
public:
/// The implementation type of the deadline timer.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined implementation_type;
#else
typedef typename service_impl_type::implementation_type implementation_type;
#endif
/// Construct a new timer service for the specified io_service.
explicit deadline_timer_service(asio::io_service& io_service)
: asio::detail::service_base<
deadline_timer_service<TimeType, TimeTraits> >(io_service),
service_impl_(asio::use_service<service_impl_type>(io_service))
{
}
/// Destroy all user-defined handler objects owned by the service.
void shutdown_service()
{
}
/// Construct a new timer implementation.
void construct(implementation_type& impl)
{
service_impl_.construct(impl);
}
/// Destroy a timer implementation.
void destroy(implementation_type& impl)
{
service_impl_.destroy(impl);
}
/// Cancel any asynchronous wait operations associated with the timer.
std::size_t cancel(implementation_type& impl, asio::error_code& ec)
{
return service_impl_.cancel(impl, ec);
}
/// Get the expiry time for the timer as an absolute time.
time_type expires_at(const implementation_type& impl) const
{
return service_impl_.expires_at(impl);
}
/// Set the expiry time for the timer as an absolute time.
std::size_t expires_at(implementation_type& impl,
const time_type& expiry_time, asio::error_code& ec)
{
return service_impl_.expires_at(impl, expiry_time, ec);
}
/// Get the expiry time for the timer relative to now.
duration_type expires_from_now(const implementation_type& impl) const
{
return service_impl_.expires_from_now(impl);
}
/// Set the expiry time for the timer relative to now.
std::size_t expires_from_now(implementation_type& impl,
const duration_type& expiry_time, asio::error_code& ec)
{
return service_impl_.expires_from_now(impl, expiry_time, ec);
}
// Perform a blocking wait on the timer.
void wait(implementation_type& impl, asio::error_code& ec)
{
service_impl_.wait(impl, ec);
}
// Start an asynchronous wait on the timer.
template <typename WaitHandler>
void async_wait(implementation_type& impl, WaitHandler handler)
{
service_impl_.async_wait(impl, handler);
}
private:
// The service that provides the platform-specific implementation.
service_impl_type& service_impl_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DEADLINE_TIMER_SERVICE_HPP

View file

@ -0,0 +1,74 @@
/bind_handler.hpp/1.18/Thu Jan 4 05:44:44 2007//
/buffer_resize_guard.hpp/1.9/Thu Jan 4 05:44:44 2007//
/buffered_stream_storage.hpp/1.5/Thu Jan 4 05:44:44 2007//
/call_stack.hpp/1.3/Thu Jan 4 05:44:44 2007//
/const_buffers_iterator.hpp/1.3/Thu Jan 4 05:44:44 2007//
/consuming_buffers.hpp/1.7/Sat Jan 13 13:41:09 2007//
/deadline_timer_service.hpp/1.7/Mon Jan 8 02:47:13 2007//
/epoll_reactor.hpp/1.40/Thu Jan 4 05:44:44 2007//
/epoll_reactor_fwd.hpp/1.3/Thu Jan 4 05:44:44 2007//
/event.hpp/1.13/Thu Jan 4 05:44:44 2007//
/fd_set_adapter.hpp/1.5/Thu Jan 4 05:44:44 2007//
/handler_alloc_helpers.hpp/1.8/Thu Jan 4 05:44:44 2007//
/handler_invoke_helpers.hpp/1.2/Thu Jan 4 05:44:44 2007//
/hash_map.hpp/1.19/Thu Mar 22 21:13:13 2007//
/io_control.hpp/1.5/Thu Jan 4 05:44:44 2007//
/kqueue_reactor.hpp/1.30/Thu Mar 22 21:08:02 2007//
/kqueue_reactor_fwd.hpp/1.3/Thu Jan 4 05:44:44 2007//
/local_free_on_block_exit.hpp/1.2/Thu Jan 4 05:44:44 2007//
/mutex.hpp/1.13/Thu Jan 4 05:44:44 2007//
/noncopyable.hpp/1.3/Thu Jan 4 05:44:44 2007//
/null_event.hpp/1.3/Thu Jan 4 05:44:44 2007//
/null_mutex.hpp/1.3/Thu Jan 4 05:44:44 2007//
/null_signal_blocker.hpp/1.3/Thu Jan 4 05:44:44 2007//
/null_thread.hpp/1.5/Mon Jan 8 22:12:46 2007//
/null_tss_ptr.hpp/1.3/Thu Jan 4 05:44:44 2007//
/old_win_sdk_compat.hpp/1.5/Sat May 12 08:16:25 2007//
/pipe_select_interrupter.hpp/1.11/Thu Jan 4 05:44:44 2007//
/pop_options.hpp/1.10/Thu Jan 4 05:44:44 2007//
/posix_event.hpp/1.16/Thu Jan 4 05:44:44 2007//
/posix_fd_set_adapter.hpp/1.4/Tue Feb 13 07:13:29 2007//
/posix_mutex.hpp/1.15/Thu Jan 4 05:44:44 2007//
/posix_signal_blocker.hpp/1.10/Sat Feb 17 22:57:37 2007//
/posix_thread.hpp/1.17/Thu Jan 4 05:44:45 2007//
/posix_tss_ptr.hpp/1.10/Thu Jan 4 05:44:45 2007//
/push_options.hpp/1.16/Thu Jan 4 05:44:45 2007//
/reactive_socket_service.hpp/1.59/Sun May 13 23:00:01 2007//
/reactor_op_queue.hpp/1.24/Thu Jan 4 05:44:45 2007//
/resolver_service.hpp/1.11/Thu Jan 4 09:06:56 2007//
/scoped_lock.hpp/1.9/Thu Jan 4 05:44:45 2007//
/select_interrupter.hpp/1.10/Thu Jan 4 05:44:45 2007//
/select_reactor.hpp/1.49/Thu Jan 4 05:44:45 2007//
/select_reactor_fwd.hpp/1.2/Thu Jan 4 05:44:45 2007//
/service_base.hpp/1.2/Thu Jan 4 05:44:45 2007//
/service_id.hpp/1.2/Thu Jan 4 05:44:45 2007//
/service_registry.hpp/1.19/Tue Feb 13 12:06:43 2007//
/service_registry_fwd.hpp/1.2/Thu Jan 4 05:44:45 2007//
/signal_blocker.hpp/1.10/Thu Jan 4 05:44:45 2007//
/signal_init.hpp/1.11/Thu Jan 4 05:44:45 2007//
/socket_holder.hpp/1.10/Thu Jan 4 05:44:45 2007//
/socket_ops.hpp/1.74/Mon May 21 12:34:39 2007//
/socket_option.hpp/1.7/Sat Feb 17 22:57:37 2007//
/socket_select_interrupter.hpp/1.15/Thu May 10 23:48:52 2007//
/socket_types.hpp/1.41/Sun May 13 07:59:21 2007//
/strand_service.hpp/1.15/Thu Jan 4 05:44:45 2007//
/task_io_service.hpp/1.18/Wed Feb 14 13:26:21 2007//
/task_io_service_fwd.hpp/1.2/Thu Jan 4 05:44:45 2007//
/thread.hpp/1.13/Thu Jan 4 05:44:45 2007//
/throw_error.hpp/1.3/Thu Jan 4 05:44:45 2007//
/timer_queue.hpp/1.6/Sun Apr 22 07:07:15 2007//
/timer_queue_base.hpp/1.2/Thu Jan 4 05:44:45 2007//
/tss_ptr.hpp/1.8/Thu Jan 4 05:44:45 2007//
/win_event.hpp/1.14/Thu Jan 4 05:44:45 2007//
/win_fd_set_adapter.hpp/1.4/Thu Jan 4 05:44:45 2007//
/win_iocp_io_service.hpp/1.24/Mon Jan 8 01:09:14 2007//
/win_iocp_io_service_fwd.hpp/1.4/Thu Jan 4 05:44:45 2007//
/win_iocp_operation.hpp/1.16/Thu Jan 4 05:44:45 2007//
/win_iocp_socket_service.hpp/1.75/Sat May 12 09:07:32 2007//
/win_mutex.hpp/1.16/Thu Jan 4 05:44:45 2007//
/win_signal_blocker.hpp/1.9/Thu Jan 4 05:44:45 2007//
/win_thread.hpp/1.20/Thu Jan 4 05:44:45 2007//
/win_tss_ptr.hpp/1.10/Thu Jan 4 05:44:45 2007//
/winsock_init.hpp/1.16/Thu Jan 4 05:44:45 2007//
/wrapped_handler.hpp/1.11/Thu Jan 4 05:44:45 2007//
D

View file

@ -0,0 +1 @@
asio/include/asio/detail

View file

@ -0,0 +1 @@
:pserver:anonymous@asio.cvs.sourceforge.net:/cvsroot/asio

View file

@ -0,0 +1,349 @@
//
// bind_handler.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_BIND_HANDLER_HPP
#define ASIO_DETAIL_BIND_HANDLER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
namespace asio {
namespace detail {
template <typename Handler, typename Arg1>
class binder1
{
public:
binder1(const Handler& handler, const Arg1& arg1)
: handler_(handler),
arg1_(arg1)
{
}
void operator()()
{
handler_(arg1_);
}
void operator()() const
{
handler_(arg1_);
}
//private:
Handler handler_;
Arg1 arg1_;
};
template <typename Handler, typename Arg1>
inline void* asio_handler_allocate(std::size_t size,
binder1<Handler, Arg1>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, &this_handler->handler_);
}
template <typename Handler, typename Arg1>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
binder1<Handler, Arg1>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, &this_handler->handler_);
}
template <typename Function, typename Handler, typename Arg1>
inline void asio_handler_invoke(const Function& function,
binder1<Handler, Arg1>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, &this_handler->handler_);
}
template <typename Handler, typename Arg1>
inline binder1<Handler, Arg1> bind_handler(const Handler& handler,
const Arg1& arg1)
{
return binder1<Handler, Arg1>(handler, arg1);
}
template <typename Handler, typename Arg1, typename Arg2>
class binder2
{
public:
binder2(const Handler& handler, const Arg1& arg1, const Arg2& arg2)
: handler_(handler),
arg1_(arg1),
arg2_(arg2)
{
}
void operator()()
{
handler_(arg1_, arg2_);
}
void operator()() const
{
handler_(arg1_, arg2_);
}
//private:
Handler handler_;
Arg1 arg1_;
Arg2 arg2_;
};
template <typename Handler, typename Arg1, typename Arg2>
inline void* asio_handler_allocate(std::size_t size,
binder2<Handler, Arg1, Arg2>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, &this_handler->handler_);
}
template <typename Handler, typename Arg1, typename Arg2>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
binder2<Handler, Arg1, Arg2>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, &this_handler->handler_);
}
template <typename Function, typename Handler, typename Arg1, typename Arg2>
inline void asio_handler_invoke(const Function& function,
binder2<Handler, Arg1, Arg2>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, &this_handler->handler_);
}
template <typename Handler, typename Arg1, typename Arg2>
inline binder2<Handler, Arg1, Arg2> bind_handler(const Handler& handler,
const Arg1& arg1, const Arg2& arg2)
{
return binder2<Handler, Arg1, Arg2>(handler, arg1, arg2);
}
template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
class binder3
{
public:
binder3(const Handler& handler, const Arg1& arg1, const Arg2& arg2,
const Arg3& arg3)
: handler_(handler),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3)
{
}
void operator()()
{
handler_(arg1_, arg2_, arg3_);
}
void operator()() const
{
handler_(arg1_, arg2_, arg3_);
}
//private:
Handler handler_;
Arg1 arg1_;
Arg2 arg2_;
Arg3 arg3_;
};
template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
inline void* asio_handler_allocate(std::size_t size,
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, &this_handler->handler_);
}
template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, &this_handler->handler_);
}
template <typename Function, typename Handler, typename Arg1, typename Arg2,
typename Arg3>
inline void asio_handler_invoke(const Function& function,
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, &this_handler->handler_);
}
template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
inline binder3<Handler, Arg1, Arg2, Arg3> bind_handler(const Handler& handler,
const Arg1& arg1, const Arg2& arg2, const Arg3& arg3)
{
return binder3<Handler, Arg1, Arg2, Arg3>(handler, arg1, arg2, arg3);
}
template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
typename Arg4>
class binder4
{
public:
binder4(const Handler& handler, const Arg1& arg1, const Arg2& arg2,
const Arg3& arg3, const Arg4& arg4)
: handler_(handler),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3),
arg4_(arg4)
{
}
void operator()()
{
handler_(arg1_, arg2_, arg3_, arg4_);
}
void operator()() const
{
handler_(arg1_, arg2_, arg3_, arg4_);
}
//private:
Handler handler_;
Arg1 arg1_;
Arg2 arg2_;
Arg3 arg3_;
Arg4 arg4_;
};
template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
typename Arg4>
inline void* asio_handler_allocate(std::size_t size,
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, &this_handler->handler_);
}
template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
typename Arg4>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, &this_handler->handler_);
}
template <typename Function, typename Handler, typename Arg1, typename Arg2,
typename Arg3, typename Arg4>
inline void asio_handler_invoke(const Function& function,
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, &this_handler->handler_);
}
template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
typename Arg4>
inline binder4<Handler, Arg1, Arg2, Arg3, Arg4> bind_handler(
const Handler& handler, const Arg1& arg1, const Arg2& arg2,
const Arg3& arg3, const Arg4& arg4)
{
return binder4<Handler, Arg1, Arg2, Arg3, Arg4>(handler, arg1, arg2, arg3,
arg4);
}
template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5>
class binder5
{
public:
binder5(const Handler& handler, const Arg1& arg1, const Arg2& arg2,
const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
: handler_(handler),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3),
arg4_(arg4),
arg5_(arg5)
{
}
void operator()()
{
handler_(arg1_, arg2_, arg3_, arg4_, arg5_);
}
void operator()() const
{
handler_(arg1_, arg2_, arg3_, arg4_, arg5_);
}
//private:
Handler handler_;
Arg1 arg1_;
Arg2 arg2_;
Arg3 arg3_;
Arg4 arg4_;
Arg5 arg5_;
};
template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5>
inline void* asio_handler_allocate(std::size_t size,
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, &this_handler->handler_);
}
template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, &this_handler->handler_);
}
template <typename Function, typename Handler, typename Arg1, typename Arg2,
typename Arg3, typename Arg4, typename Arg5>
inline void asio_handler_invoke(const Function& function,
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, &this_handler->handler_);
}
template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5>
inline binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5> bind_handler(
const Handler& handler, const Arg1& arg1, const Arg2& arg2,
const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
{
return binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>(handler, arg1, arg2,
arg3, arg4, arg5);
}
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_BIND_HANDLER_HPP

View file

@ -0,0 +1,70 @@
//
// buffer_resize_guard.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP
#define ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <limits>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
// Helper class to manage buffer resizing in an exception safe way.
template <typename Buffer>
class buffer_resize_guard
{
public:
// Constructor.
buffer_resize_guard(Buffer& buffer)
: buffer_(buffer),
old_size_(buffer.size())
{
}
// Destructor rolls back the buffer resize unless commit was called.
~buffer_resize_guard()
{
if (old_size_
!= std::numeric_limits<size_t>::max BOOST_PREVENT_MACRO_SUBSTITUTION())
{
buffer_.resize(old_size_);
}
}
// Commit the resize transaction.
void commit()
{
old_size_
= std::numeric_limits<size_t>::max BOOST_PREVENT_MACRO_SUBSTITUTION();
}
private:
// The buffer being managed.
Buffer& buffer_;
// The size of the buffer at the time the guard was constructed.
size_t old_size_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP

View file

@ -0,0 +1,127 @@
//
// buffered_stream_storage.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP
#define ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <vector>
#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
class buffered_stream_storage
{
public:
// The type of the bytes stored in the buffer.
typedef unsigned char byte_type;
// The type used for offsets into the buffer.
typedef std::size_t size_type;
// Constructor.
explicit buffered_stream_storage(std::size_t capacity)
: begin_offset_(0),
end_offset_(0),
buffer_(capacity)
{
}
/// Clear the buffer.
void clear()
{
begin_offset_ = 0;
end_offset_ = 0;
}
// Return a pointer to the beginning of the unread data.
byte_type* data()
{
return &buffer_[0] + begin_offset_;
}
// Return a pointer to the beginning of the unread data.
const byte_type* data() const
{
return &buffer_[0] + begin_offset_;
}
// Is there no unread data in the buffer.
bool empty() const
{
return begin_offset_ == end_offset_;
}
// Return the amount of unread data the is in the buffer.
size_type size() const
{
return end_offset_ - begin_offset_;
}
// Resize the buffer to the specified length.
void resize(size_type length)
{
assert(length <= capacity());
if (begin_offset_ + length <= capacity())
{
end_offset_ = begin_offset_ + length;
}
else
{
using namespace std; // For memmove.
memmove(&buffer_[0], &buffer_[0] + begin_offset_, size());
end_offset_ = length;
begin_offset_ = 0;
}
}
// Return the maximum size for data in the buffer.
size_type capacity() const
{
return buffer_.size();
}
// Consume multiple bytes from the beginning of the buffer.
void consume(size_type count)
{
assert(begin_offset_ + count <= end_offset_);
begin_offset_ += count;
if (empty())
clear();
}
private:
// The offset to the beginning of the unread data.
size_type begin_offset_;
// The offset to the end of the unread data.
size_type end_offset_;
// The data in the buffer.
std::vector<byte_type> buffer_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP

View file

@ -0,0 +1,90 @@
//
// call_stack.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_CALL_STACK_HPP
#define ASIO_DETAIL_CALL_STACK_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/tss_ptr.hpp"
namespace asio {
namespace detail {
// Helper class to determine whether or not the current thread is inside an
// invocation of io_service::run() for a specified io_service object.
template <typename Owner>
class call_stack
{
public:
// Context class automatically pushes an owner on to the stack.
class context
: private noncopyable
{
public:
// Push the owner on to the stack.
explicit context(Owner* d)
: owner_(d),
next_(call_stack<Owner>::top_)
{
call_stack<Owner>::top_ = this;
}
// Pop the owner from the stack.
~context()
{
call_stack<Owner>::top_ = next_;
}
private:
friend class call_stack<Owner>;
// The owner associated with the context.
Owner* owner_;
// The next element in the stack.
context* next_;
};
friend class context;
// Determine whether the specified owner is on the stack.
static bool contains(Owner* d)
{
context* elem = top_;
while (elem)
{
if (elem->owner_ == d)
return true;
elem = elem->next_;
}
return false;
}
private:
// The top of the stack of calls for the current thread.
static tss_ptr<context> top_;
};
template <typename Owner>
tss_ptr<typename call_stack<Owner>::context>
call_stack<Owner>::top_;
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_CALL_STACK_HPP

View file

@ -0,0 +1,151 @@
//
// const_buffers_iterator.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP
#define ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/buffer.hpp"
namespace asio {
namespace detail {
// A proxy iterator for a sub-range in a list of buffers.
template <typename ConstBufferSequence>
class const_buffers_iterator
: public boost::iterator_facade<const_buffers_iterator<ConstBufferSequence>,
const char, boost::bidirectional_traversal_tag>
{
public:
// Default constructor creates an iterator in an undefined state.
const_buffers_iterator()
{
}
// Create an iterator for the specified position.
const_buffers_iterator(const ConstBufferSequence& buffers,
std::size_t position)
: begin_(buffers.begin()),
current_(buffers.begin()),
end_(buffers.end()),
position_(0)
{
while (current_ != end_)
{
current_buffer_ = *current_;
std::size_t buffer_size = asio::buffer_size(current_buffer_);
if (position - position_ < buffer_size)
{
current_buffer_position_ = position - position_;
position_ = position;
return;
}
position_ += buffer_size;
++current_;
}
current_buffer_ = asio::const_buffer();
current_buffer_position_ = 0;
}
std::size_t position() const
{
return position_;
}
private:
friend class boost::iterator_core_access;
void increment()
{
if (current_ == end_)
return;
++position_;
++current_buffer_position_;
if (current_buffer_position_ != asio::buffer_size(current_buffer_))
return;
++current_;
current_buffer_position_ = 0;
while (current_ != end_)
{
current_buffer_ = *current_;
if (asio::buffer_size(current_buffer_) > 0)
return;
++current_;
}
}
void decrement()
{
if (position_ == 0)
return;
--position_;
if (current_buffer_position_ != 0)
{
--current_buffer_position_;
return;
}
typename ConstBufferSequence::const_iterator iter = current_;
while (iter != begin_)
{
--iter;
asio::const_buffer buffer = *iter;
std::size_t buffer_size = asio::buffer_size(buffer);
if (buffer_size > 0)
{
current_ = iter;
current_buffer_ = buffer;
current_buffer_position_ = buffer_size - 1;
return;
}
}
}
bool equal(const const_buffers_iterator& other) const
{
return position_ == other.position_;
}
const char& dereference() const
{
return asio::buffer_cast<const char*>(
current_buffer_)[current_buffer_position_];
}
asio::const_buffer current_buffer_;
std::size_t current_buffer_position_;
typename ConstBufferSequence::const_iterator begin_;
typename ConstBufferSequence::const_iterator current_;
typename ConstBufferSequence::const_iterator end_;
std::size_t position_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP

View file

@ -0,0 +1,205 @@
//
// consuming_buffers.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_CONSUMING_BUFFERS_HPP
#define ASIO_DETAIL_CONSUMING_BUFFERS_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <algorithm>
#include <cstddef>
#include <boost/config.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
// A proxy iterator for a sub-range in a list of buffers.
template <typename Buffer, typename Buffer_Iterator>
class consuming_buffers_iterator
: public boost::iterator_facade<
consuming_buffers_iterator<Buffer, Buffer_Iterator>,
const Buffer, boost::forward_traversal_tag>
{
public:
// Default constructor creates an end iterator.
consuming_buffers_iterator()
: at_end_(true)
{
}
// Construct with a buffer for the first entry and an iterator
// range for the remaining entries.
consuming_buffers_iterator(bool at_end, const Buffer& first,
Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder)
: at_end_(at_end),
first_(buffer(first, max_size)),
begin_remainder_(begin_remainder),
end_remainder_(end_remainder),
offset_(0)
{
}
private:
friend class boost::iterator_core_access;
enum { max_size = 65536 };
void increment()
{
if (!at_end_)
{
if (begin_remainder_ == end_remainder_
|| offset_ + buffer_size(first_) >= max_size)
{
at_end_ = true;
}
else
{
offset_ += buffer_size(first_);
first_ = buffer(*begin_remainder_++, max_size - offset_);
}
}
}
bool equal(const consuming_buffers_iterator& other) const
{
if (at_end_ && other.at_end_)
return true;
return !at_end_ && !other.at_end_
&& buffer_cast<const void*>(first_)
== buffer_cast<const void*>(other.first_)
&& buffer_size(first_) == buffer_size(other.first_)
&& begin_remainder_ == other.begin_remainder_
&& end_remainder_ == other.end_remainder_;
}
const Buffer& dereference() const
{
return first_;
}
bool at_end_;
Buffer first_;
Buffer_Iterator begin_remainder_;
Buffer_Iterator end_remainder_;
std::size_t offset_;
};
// A proxy for a sub-range in a list of buffers.
template <typename Buffer, typename Buffers>
class consuming_buffers
{
public:
// The type for each element in the list of buffers.
typedef Buffer value_type;
// A forward-only iterator type that may be used to read elements.
typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator>
const_iterator;
// Construct to represent the entire list of buffers.
consuming_buffers(const Buffers& buffers)
: buffers_(buffers),
at_end_(buffers_.begin() == buffers_.end()),
first_(*buffers_.begin()),
begin_remainder_(buffers_.begin())
{
if (!at_end_)
++begin_remainder_;
}
// Copy constructor.
consuming_buffers(const consuming_buffers& other)
: buffers_(other.buffers_),
at_end_(other.at_end_),
first_(other.first_),
begin_remainder_(buffers_.begin())
{
typename Buffers::const_iterator first = other.buffers_.begin();
typename Buffers::const_iterator second = other.begin_remainder_;
std::advance(begin_remainder_, std::distance(first, second));
}
// Assignment operator.
consuming_buffers& operator=(const consuming_buffers& other)
{
buffers_ = other.buffers_;
at_end_ = other.at_end_;
first_ = other.first_;
begin_remainder_ = buffers_.begin();
typename Buffers::const_iterator first = other.buffers_.begin();
typename Buffers::const_iterator second = other.begin_remainder_;
std::advance(begin_remainder_, std::distance(first, second));
return *this;
}
// Get a forward-only iterator to the first element.
const_iterator begin() const
{
return const_iterator(at_end_, first_, begin_remainder_, buffers_.end());
}
// Get a forward-only iterator for one past the last element.
const_iterator end() const
{
return const_iterator();
}
// Consume the specified number of bytes from the buffers.
void consume(std::size_t size)
{
// Remove buffers from the start until the specified size is reached.
while (size > 0 && !at_end_)
{
if (buffer_size(first_) <= size)
{
size -= buffer_size(first_);
if (begin_remainder_ == buffers_.end())
at_end_ = true;
else
first_ = *begin_remainder_++;
}
else
{
first_ = first_ + size;
size = 0;
}
}
// Remove any more empty buffers at the start.
while (!at_end_ && buffer_size(first_) == 0)
{
if (begin_remainder_ == buffers_.end())
at_end_ = true;
else
first_ = *begin_remainder_++;
}
}
private:
Buffers buffers_;
bool at_end_;
Buffer first_;
typename Buffers::const_iterator begin_remainder_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP

View file

@ -0,0 +1,199 @@
//
// deadline_timer_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP
#define ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/service_base.hpp"
#include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/timer_queue.hpp"
namespace asio {
namespace detail {
template <typename Time_Traits, typename Timer_Scheduler>
class deadline_timer_service
: public asio::detail::service_base<
deadline_timer_service<Time_Traits, Timer_Scheduler> >
{
public:
// The time type.
typedef typename Time_Traits::time_type time_type;
// The duration type.
typedef typename Time_Traits::duration_type duration_type;
// The implementation type of the timer. This type is dependent on the
// underlying implementation of the timer service.
struct implementation_type
: private asio::detail::noncopyable
{
time_type expiry;
bool might_have_pending_waits;
};
// Constructor.
deadline_timer_service(asio::io_service& io_service)
: asio::detail::service_base<
deadline_timer_service<Time_Traits, Timer_Scheduler> >(io_service),
scheduler_(asio::use_service<Timer_Scheduler>(io_service))
{
scheduler_.add_timer_queue(timer_queue_);
}
// Destructor.
~deadline_timer_service()
{
scheduler_.remove_timer_queue(timer_queue_);
}
// Destroy all user-defined handler objects owned by the service.
void shutdown_service()
{
}
// Construct a new timer implementation.
void construct(implementation_type& impl)
{
impl.expiry = time_type();
impl.might_have_pending_waits = false;
}
// Destroy a timer implementation.
void destroy(implementation_type& impl)
{
asio::error_code ec;
cancel(impl, ec);
}
// Cancel any asynchronous wait operations associated with the timer.
std::size_t cancel(implementation_type& impl, asio::error_code& ec)
{
if (!impl.might_have_pending_waits)
{
ec = asio::error_code();
return 0;
}
std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl);
impl.might_have_pending_waits = false;
ec = asio::error_code();
return count;
}
// Get the expiry time for the timer as an absolute time.
time_type expires_at(const implementation_type& impl) const
{
return impl.expiry;
}
// Set the expiry time for the timer as an absolute time.
std::size_t expires_at(implementation_type& impl,
const time_type& expiry_time, asio::error_code& ec)
{
std::size_t count = cancel(impl, ec);
impl.expiry = expiry_time;
ec = asio::error_code();
return count;
}
// Get the expiry time for the timer relative to now.
duration_type expires_from_now(const implementation_type& impl) const
{
return Time_Traits::subtract(expires_at(impl), Time_Traits::now());
}
// Set the expiry time for the timer relative to now.
std::size_t expires_from_now(implementation_type& impl,
const duration_type& expiry_time, asio::error_code& ec)
{
return expires_at(impl,
Time_Traits::add(Time_Traits::now(), expiry_time), ec);
}
// Perform a blocking wait on the timer.
void wait(implementation_type& impl, asio::error_code& ec)
{
time_type now = Time_Traits::now();
while (Time_Traits::less_than(now, impl.expiry))
{
boost::posix_time::time_duration timeout =
Time_Traits::to_posix_duration(Time_Traits::subtract(impl.expiry, now));
::timeval tv;
tv.tv_sec = timeout.total_seconds();
tv.tv_usec = timeout.total_microseconds() % 1000000;
asio::error_code ec;
socket_ops::select(0, 0, 0, 0, &tv, ec);
now = Time_Traits::now();
}
ec = asio::error_code();
}
template <typename Handler>
class wait_handler
{
public:
wait_handler(asio::io_service& io_service, Handler handler)
: io_service_(io_service),
work_(io_service),
handler_(handler)
{
}
void operator()(const asio::error_code& result)
{
io_service_.post(detail::bind_handler(handler_, result));
}
private:
asio::io_service& io_service_;
asio::io_service::work work_;
Handler handler_;
};
// Start an asynchronous wait on the timer.
template <typename Handler>
void async_wait(implementation_type& impl, Handler handler)
{
impl.might_have_pending_waits = true;
scheduler_.schedule_timer(timer_queue_, impl.expiry,
wait_handler<Handler>(this->io_service(), handler), &impl);
}
private:
// The queue of timers.
timer_queue<Time_Traits> timer_queue_;
// The object that schedules and executes timers. Usually a reactor.
Timer_Scheduler& scheduler_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP

View file

@ -0,0 +1,613 @@
//
// epoll_reactor.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_EPOLL_REACTOR_HPP
#define ASIO_DETAIL_EPOLL_REACTOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/epoll_reactor_fwd.hpp"
#if defined(ASIO_HAS_EPOLL)
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <vector>
#include <sys/epoll.h>
#include <boost/config.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/throw_exception.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/system_error.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/hash_map.hpp"
#include "asio/detail/mutex.hpp"
#include "asio/detail/task_io_service.hpp"
#include "asio/detail/thread.hpp"
#include "asio/detail/reactor_op_queue.hpp"
#include "asio/detail/select_interrupter.hpp"
#include "asio/detail/service_base.hpp"
#include "asio/detail/signal_blocker.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/timer_queue.hpp"
namespace asio {
namespace detail {
template <bool Own_Thread>
class epoll_reactor
: public asio::detail::service_base<epoll_reactor<Own_Thread> >
{
public:
// Constructor.
epoll_reactor(asio::io_service& io_service)
: asio::detail::service_base<epoll_reactor<Own_Thread> >(io_service),
mutex_(),
epoll_fd_(do_epoll_create()),
wait_in_progress_(false),
interrupter_(),
read_op_queue_(),
write_op_queue_(),
except_op_queue_(),
pending_cancellations_(),
stop_thread_(false),
thread_(0),
shutdown_(false)
{
// Start the reactor's internal thread only if needed.
if (Own_Thread)
{
asio::detail::signal_blocker sb;
thread_ = new asio::detail::thread(
bind_handler(&epoll_reactor::call_run_thread, this));
}
// Add the interrupter's descriptor to epoll.
epoll_event ev = { 0, { 0 } };
ev.events = EPOLLIN | EPOLLERR;
ev.data.fd = interrupter_.read_descriptor();
epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
}
// Destructor.
~epoll_reactor()
{
shutdown_service();
close(epoll_fd_);
}
// Destroy all user-defined handler objects owned by the service.
void shutdown_service()
{
asio::detail::mutex::scoped_lock lock(mutex_);
shutdown_ = true;
stop_thread_ = true;
lock.unlock();
if (thread_)
{
interrupter_.interrupt();
thread_->join();
delete thread_;
thread_ = 0;
}
read_op_queue_.destroy_operations();
write_op_queue_.destroy_operations();
except_op_queue_.destroy_operations();
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
timer_queues_[i]->destroy_timers();
timer_queues_.clear();
}
// Register a socket with the reactor. Returns 0 on success, system error
// code on failure.
int register_descriptor(socket_type descriptor)
{
// No need to lock according to epoll documentation.
epoll_event ev = { 0, { 0 } };
ev.events = 0;
ev.data.fd = descriptor;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
if (result != 0)
return errno;
return 0;
}
// Start a new read operation. The handler object will be invoked when the
// given descriptor is ready to be read, or an error has occurred.
template <typename Handler>
void start_read_op(socket_type descriptor, Handler handler)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (shutdown_)
return;
if (!read_op_queue_.has_operation(descriptor))
if (handler(asio::error_code()))
return;
if (read_op_queue_.enqueue_operation(descriptor, handler))
{
epoll_event ev = { 0, { 0 } };
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;
if (write_op_queue_.has_operation(descriptor))
ev.events |= EPOLLOUT;
if (except_op_queue_.has_operation(descriptor))
ev.events |= EPOLLPRI;
ev.data.fd = descriptor;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0)
{
asio::error_code ec(errno, asio::native_ecat);
read_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
}
// Start a new write operation. The handler object will be invoked when the
// given descriptor is ready to be written, or an error has occurred.
template <typename Handler>
void start_write_op(socket_type descriptor, Handler handler)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (shutdown_)
return;
if (!write_op_queue_.has_operation(descriptor))
if (handler(asio::error_code()))
return;
if (write_op_queue_.enqueue_operation(descriptor, handler))
{
epoll_event ev = { 0, { 0 } };
ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP;
if (read_op_queue_.has_operation(descriptor))
ev.events |= EPOLLIN;
if (except_op_queue_.has_operation(descriptor))
ev.events |= EPOLLPRI;
ev.data.fd = descriptor;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0)
{
asio::error_code ec(errno, asio::native_ecat);
write_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
}
// Start a new exception operation. The handler object will be invoked when
// the given descriptor has exception information, or an error has occurred.
template <typename Handler>
void start_except_op(socket_type descriptor, Handler handler)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (shutdown_)
return;
if (except_op_queue_.enqueue_operation(descriptor, handler))
{
epoll_event ev = { 0, { 0 } };
ev.events = EPOLLPRI | EPOLLERR | EPOLLHUP;
if (read_op_queue_.has_operation(descriptor))
ev.events |= EPOLLIN;
if (write_op_queue_.has_operation(descriptor))
ev.events |= EPOLLOUT;
ev.data.fd = descriptor;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0)
{
asio::error_code ec(errno, asio::native_ecat);
except_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
}
// Start new write and exception operations. The handler object will be
// invoked when the given descriptor is ready for writing or has exception
// information available, or an error has occurred.
template <typename Handler>
void start_write_and_except_ops(socket_type descriptor, Handler handler)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (shutdown_)
return;
bool need_mod = write_op_queue_.enqueue_operation(descriptor, handler);
need_mod = except_op_queue_.enqueue_operation(descriptor, handler)
&& need_mod;
if (need_mod)
{
epoll_event ev = { 0, { 0 } };
ev.events = EPOLLOUT | EPOLLPRI | EPOLLERR | EPOLLHUP;
if (read_op_queue_.has_operation(descriptor))
ev.events |= EPOLLIN;
ev.data.fd = descriptor;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0)
{
asio::error_code ec(errno, asio::native_ecat);
write_op_queue_.dispatch_all_operations(descriptor, ec);
except_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
}
// Cancel all operations associated with the given descriptor. The
// handlers associated with the descriptor will be invoked with the
// operation_aborted error.
void cancel_ops(socket_type descriptor)
{
asio::detail::mutex::scoped_lock lock(mutex_);
cancel_ops_unlocked(descriptor);
}
// Enqueue cancellation of all operations associated with the given
// descriptor. The handlers associated with the descriptor will be invoked
// with the operation_aborted error. This function does not acquire the
// epoll_reactor's mutex, and so should only be used from within a reactor
// handler.
void enqueue_cancel_ops_unlocked(socket_type descriptor)
{
pending_cancellations_.push_back(descriptor);
}
// Cancel any operations that are running against the descriptor and remove
// its registration from the reactor.
void close_descriptor(socket_type descriptor)
{
asio::detail::mutex::scoped_lock lock(mutex_);
// Remove the descriptor from epoll.
epoll_event ev = { 0, { 0 } };
epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
// Cancel any outstanding operations associated with the descriptor.
cancel_ops_unlocked(descriptor);
}
// Add a new timer queue to the reactor.
template <typename Time_Traits>
void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
{
asio::detail::mutex::scoped_lock lock(mutex_);
timer_queues_.push_back(&timer_queue);
}
// Remove a timer queue from the reactor.
template <typename Time_Traits>
void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
{
asio::detail::mutex::scoped_lock lock(mutex_);
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
{
if (timer_queues_[i] == &timer_queue)
{
timer_queues_.erase(timer_queues_.begin() + i);
return;
}
}
}
// Schedule a timer in the given timer queue to expire at the specified
// absolute time. The handler object will be invoked when the timer expires.
template <typename Time_Traits, typename Handler>
void schedule_timer(timer_queue<Time_Traits>& timer_queue,
const typename Time_Traits::time_type& time, Handler handler, void* token)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (!shutdown_)
if (timer_queue.enqueue_timer(time, handler, token))
interrupter_.interrupt();
}
// Cancel the timer associated with the given token. Returns the number of
// handlers that have been posted or dispatched.
template <typename Time_Traits>
std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
{
asio::detail::mutex::scoped_lock lock(mutex_);
return timer_queue.cancel_timer(token);
}
private:
friend class task_io_service<epoll_reactor<Own_Thread> >;
// Run epoll once until interrupted or events are ready to be dispatched.
void run(bool block)
{
asio::detail::mutex::scoped_lock lock(mutex_);
// Dispatch any operation cancellations that were made while the select
// loop was not running.
read_op_queue_.dispatch_cancellations();
write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations();
// Check if the thread is supposed to stop.
if (stop_thread_)
{
// Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
return;
}
// We can return immediately if there's no work to do and the reactor is
// not supposed to block.
if (!block && read_op_queue_.empty() && write_op_queue_.empty()
&& except_op_queue_.empty() && all_timer_queues_are_empty())
{
// Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
return;
}
int timeout = block ? get_timeout() : 0;
wait_in_progress_ = true;
lock.unlock();
// Block on the epoll descriptor.
epoll_event events[128];
int num_events = epoll_wait(epoll_fd_, events, 128, timeout);
lock.lock();
wait_in_progress_ = false;
// Block signals while dispatching operations.
asio::detail::signal_blocker sb;
// Dispatch the waiting events.
for (int i = 0; i < num_events; ++i)
{
int descriptor = events[i].data.fd;
if (descriptor == interrupter_.read_descriptor())
{
interrupter_.reset();
}
else
{
if (events[i].events & (EPOLLERR | EPOLLHUP))
{
asio::error_code ec;
except_op_queue_.dispatch_all_operations(descriptor, ec);
read_op_queue_.dispatch_all_operations(descriptor, ec);
write_op_queue_.dispatch_all_operations(descriptor, ec);
epoll_event ev = { 0, { 0 } };
ev.events = 0;
ev.data.fd = descriptor;
epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
}
else
{
bool more_reads = false;
bool more_writes = false;
bool more_except = false;
asio::error_code ec;
// Exception operations must be processed first to ensure that any
// out-of-band data is read before normal data.
if (events[i].events & EPOLLPRI)
more_except = except_op_queue_.dispatch_operation(descriptor, ec);
else
more_except = except_op_queue_.has_operation(descriptor);
if (events[i].events & EPOLLIN)
more_reads = read_op_queue_.dispatch_operation(descriptor, ec);
else
more_reads = read_op_queue_.has_operation(descriptor);
if (events[i].events & EPOLLOUT)
more_writes = write_op_queue_.dispatch_operation(descriptor, ec);
else
more_writes = write_op_queue_.has_operation(descriptor);
epoll_event ev = { 0, { 0 } };
ev.events = EPOLLERR | EPOLLHUP;
if (more_reads)
ev.events |= EPOLLIN;
if (more_writes)
ev.events |= EPOLLOUT;
if (more_except)
ev.events |= EPOLLPRI;
ev.data.fd = descriptor;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0)
{
ec = asio::error_code(errno, asio::native_ecat);
read_op_queue_.dispatch_all_operations(descriptor, ec);
write_op_queue_.dispatch_all_operations(descriptor, ec);
except_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
}
}
read_op_queue_.dispatch_cancellations();
write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations();
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
timer_queues_[i]->dispatch_timers();
// Issue any pending cancellations.
for (size_t i = 0; i < pending_cancellations_.size(); ++i)
cancel_ops_unlocked(pending_cancellations_[i]);
pending_cancellations_.clear();
// Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
}
// Run the select loop in the thread.
void run_thread()
{
asio::detail::mutex::scoped_lock lock(mutex_);
while (!stop_thread_)
{
lock.unlock();
run(true);
lock.lock();
}
}
// Entry point for the select loop thread.
static void call_run_thread(epoll_reactor* reactor)
{
reactor->run_thread();
}
// Interrupt the select loop.
void interrupt()
{
interrupter_.interrupt();
}
// The hint to pass to epoll_create to size its data structures.
enum { epoll_size = 20000 };
// Create the epoll file descriptor. Throws an exception if the descriptor
// cannot be created.
static int do_epoll_create()
{
int fd = epoll_create(epoll_size);
if (fd == -1)
{
boost::throw_exception(asio::system_error(
asio::error_code(errno, asio::native_ecat),
"epoll"));
}
return fd;
}
// Check if all timer queues are empty.
bool all_timer_queues_are_empty() const
{
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
if (!timer_queues_[i]->empty())
return false;
return true;
}
// Get the timeout value for the epoll_wait call. The timeout value is
// returned as a number of milliseconds. A return value of -1 indicates
// that epoll_wait should block indefinitely.
int get_timeout()
{
if (all_timer_queues_are_empty())
return -1;
// By default we will wait no longer than 5 minutes. This will ensure that
// any changes to the system clock are detected after no longer than this.
boost::posix_time::time_duration minimum_wait_duration
= boost::posix_time::minutes(5);
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
{
boost::posix_time::time_duration wait_duration
= timer_queues_[i]->wait_duration();
if (wait_duration < minimum_wait_duration)
minimum_wait_duration = wait_duration;
}
if (minimum_wait_duration > boost::posix_time::time_duration())
{
return minimum_wait_duration.total_milliseconds();
}
else
{
return 0;
}
}
// Cancel all operations associated with the given descriptor. The do_cancel
// function of the handler objects will be invoked. This function does not
// acquire the epoll_reactor's mutex.
void cancel_ops_unlocked(socket_type descriptor)
{
bool interrupt = read_op_queue_.cancel_operations(descriptor);
interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt;
interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt;
if (interrupt)
interrupter_.interrupt();
}
// Mutex to protect access to internal data.
asio::detail::mutex mutex_;
// The epoll file descriptor.
int epoll_fd_;
// Whether the epoll_wait call is currently in progress
bool wait_in_progress_;
// The interrupter is used to break a blocking epoll_wait call.
select_interrupter interrupter_;
// The queue of read operations.
reactor_op_queue<socket_type> read_op_queue_;
// The queue of write operations.
reactor_op_queue<socket_type> write_op_queue_;
// The queue of except operations.
reactor_op_queue<socket_type> except_op_queue_;
// The timer queues.
std::vector<timer_queue_base*> timer_queues_;
// The descriptors that are pending cancellation.
std::vector<socket_type> pending_cancellations_;
// Does the reactor loop thread need to stop.
bool stop_thread_;
// The thread that is running the reactor loop.
asio::detail::thread* thread_;
// Whether the service has been shut down.
bool shutdown_;
};
} // namespace detail
} // namespace asio
#endif // defined(ASIO_HAS_EPOLL)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_EPOLL_REACTOR_HPP

View file

@ -0,0 +1,47 @@
//
// epoll_reactor_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP
#define ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#if !defined(ASIO_DISABLE_EPOLL)
#if defined(__linux__) // This service is only supported on Linux.
#include "asio/detail/push_options.hpp"
#include <linux/version.h>
#include "asio/detail/pop_options.hpp"
#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45) // Only kernels >= 2.5.45.
// Define this to indicate that epoll is supported on the target platform.
#define ASIO_HAS_EPOLL 1
namespace asio {
namespace detail {
template <bool Own_Thread>
class epoll_reactor;
} // namespace detail
} // namespace asio
#endif // LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45)
#endif // defined(__linux__)
#endif // !defined(ASIO_DISABLE_EPOLL)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP

View file

@ -0,0 +1,50 @@
//
// event.hpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_EVENT_HPP
#define ASIO_DETAIL_EVENT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_HAS_THREADS)
# include "asio/detail/null_event.hpp"
#elif defined(BOOST_WINDOWS)
# include "asio/detail/win_event.hpp"
#elif defined(BOOST_HAS_PTHREADS)
# include "asio/detail/posix_event.hpp"
#else
# error Only Windows and POSIX are supported!
#endif
namespace asio {
namespace detail {
#if !defined(BOOST_HAS_THREADS)
typedef null_event event;
#elif defined(BOOST_WINDOWS)
typedef win_event event;
#elif defined(BOOST_HAS_PTHREADS)
typedef posix_event event;
#endif
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_EVENT_HPP

View file

@ -0,0 +1,41 @@
//
// fd_set_adapter.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_FD_SET_ADAPTER_HPP
#define ASIO_DETAIL_FD_SET_ADAPTER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/posix_fd_set_adapter.hpp"
#include "asio/detail/win_fd_set_adapter.hpp"
namespace asio {
namespace detail {
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
typedef win_fd_set_adapter fd_set_adapter;
#else
typedef posix_fd_set_adapter fd_set_adapter;
#endif
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_FD_SET_ADAPTER_HPP

View file

@ -0,0 +1,256 @@
//
// handler_alloc_helpers.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP
#define ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/detail/workaround.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/handler_alloc_hook.hpp"
#include "asio/detail/noncopyable.hpp"
// Calls to asio_handler_allocate and asio_handler_deallocate must be made from
// a namespace that does not contain any overloads of these functions. The
// asio_handler_alloc_helpers namespace is defined here for that purpose.
namespace asio_handler_alloc_helpers {
template <typename Handler>
inline void* allocate(std::size_t s, Handler* h)
{
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
return ::operator new(s);
#else
using namespace asio;
return asio_handler_allocate(s, h);
#endif
}
template <typename Handler>
inline void deallocate(void* p, std::size_t s, Handler* h)
{
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
::operator delete(p);
#else
using namespace asio;
asio_handler_deallocate(p, s, h);
#endif
}
} // namespace asio_handler_alloc_helpers
namespace asio {
namespace detail {
// Traits for handler allocation.
template <typename Handler, typename Object>
struct handler_alloc_traits
{
typedef Handler handler_type;
typedef Object value_type;
typedef Object* pointer_type;
BOOST_STATIC_CONSTANT(std::size_t, value_size = sizeof(Object));
};
template <typename Alloc_Traits>
class handler_ptr;
// Helper class to provide RAII on uninitialised handler memory.
template <typename Alloc_Traits>
class raw_handler_ptr
: private noncopyable
{
public:
typedef typename Alloc_Traits::handler_type handler_type;
typedef typename Alloc_Traits::value_type value_type;
typedef typename Alloc_Traits::pointer_type pointer_type;
BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size);
// Constructor allocates the memory.
raw_handler_ptr(handler_type& handler)
: handler_(handler),
pointer_(static_cast<pointer_type>(
asio_handler_alloc_helpers::allocate(value_size, &handler_)))
{
}
// Destructor automatically deallocates memory, unless it has been stolen by
// a handler_ptr object.
~raw_handler_ptr()
{
if (pointer_)
asio_handler_alloc_helpers::deallocate(
pointer_, value_size, &handler_);
}
private:
friend class handler_ptr<Alloc_Traits>;
handler_type& handler_;
pointer_type pointer_;
};
// Helper class to provide RAII on uninitialised handler memory.
template <typename Alloc_Traits>
class handler_ptr
: private noncopyable
{
public:
typedef typename Alloc_Traits::handler_type handler_type;
typedef typename Alloc_Traits::value_type value_type;
typedef typename Alloc_Traits::pointer_type pointer_type;
BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size);
typedef raw_handler_ptr<Alloc_Traits> raw_ptr_type;
// Take ownership of existing memory.
handler_ptr(handler_type& handler, pointer_type pointer)
: handler_(handler),
pointer_(pointer)
{
}
// Construct object in raw memory and take ownership if construction succeeds.
handler_ptr(raw_ptr_type& raw_ptr)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type)
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1, a2))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2, typename Arg3>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
typename Arg5>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
Arg5& a5)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
typename Arg5, typename Arg6>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
Arg5& a5, Arg6& a6)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
typename Arg5, typename Arg6, typename Arg7>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
Arg5& a5, Arg6& a6, Arg7& a7)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6, a7))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
typename Arg5, typename Arg6, typename Arg7, typename Arg8>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
Arg5& a5, Arg6& a6, Arg7& a7, Arg8& a8)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(
a1, a2, a3, a4, a5, a6, a7, a8))
{
raw_ptr.pointer_ = 0;
}
// Destructor automatically deallocates memory, unless it has been released.
~handler_ptr()
{
reset();
}
// Get the memory.
pointer_type get() const
{
return pointer_;
}
// Release ownership of the memory.
pointer_type release()
{
pointer_type tmp = pointer_;
pointer_ = 0;
return tmp;
}
// Explicitly destroy and deallocate the memory.
void reset()
{
if (pointer_)
{
pointer_->value_type::~value_type();
asio_handler_alloc_helpers::deallocate(
pointer_, value_size, &handler_);
pointer_ = 0;
}
}
private:
handler_type& handler_;
pointer_type pointer_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP

View file

@ -0,0 +1,47 @@
//
// handler_invoke_helpers.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP
#define ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/detail/workaround.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/handler_invoke_hook.hpp"
// Calls to asio_handler_invoke must be made from a namespace that does not
// contain overloads of this function. The asio_handler_invoke_helpers
// namespace is defined here for that purpose.
namespace asio_handler_invoke_helpers {
template <typename Function, typename Context>
inline void invoke(const Function& function, Context* context)
{
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
Function tmp(function);
tmp();
#else
using namespace asio;
asio_handler_invoke(function, context);
#endif
}
} // namespace asio_handler_invoke_helpers
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP

View file

@ -0,0 +1,209 @@
//
// hash_map.hpp
// ~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_HASH_MAP_HPP
#define ASIO_DETAIL_HASH_MAP_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cassert>
#include <list>
#include <utility>
#include <boost/functional/hash.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
namespace asio {
namespace detail {
template <typename T>
inline std::size_t calculate_hash_value(const T& t)
{
return boost::hash_value(t);
}
#if defined(_WIN64)
inline std::size_t calculate_hash_value(SOCKET s)
{
return static_cast<std::size_t>(s);
}
#endif // defined(_WIN64)
template <typename K, typename V>
class hash_map
: private noncopyable
{
public:
// The type of a value in the map.
typedef std::pair<K, V> value_type;
// The type of a non-const iterator over the hash map.
typedef typename std::list<value_type>::iterator iterator;
// The type of a const iterator over the hash map.
typedef typename std::list<value_type>::const_iterator const_iterator;
// Constructor.
hash_map()
{
// Initialise all buckets to empty.
for (size_t i = 0; i < num_buckets; ++i)
buckets_[i].first = buckets_[i].last = values_.end();
}
// Get an iterator for the beginning of the map.
iterator begin()
{
return values_.begin();
}
// Get an iterator for the beginning of the map.
const_iterator begin() const
{
return values_.begin();
}
// Get an iterator for the end of the map.
iterator end()
{
return values_.end();
}
// Get an iterator for the end of the map.
const_iterator end() const
{
return values_.end();
}
// Check whether the map is empty.
bool empty() const
{
return values_.empty();
}
// Find an entry in the map.
iterator find(const K& k)
{
size_t bucket = calculate_hash_value(k) % num_buckets;
iterator it = buckets_[bucket].first;
if (it == values_.end())
return values_.end();
iterator end = buckets_[bucket].last;
++end;
while (it != end)
{
if (it->first == k)
return it;
++it;
}
return values_.end();
}
// Find an entry in the map.
const_iterator find(const K& k) const
{
size_t bucket = calculate_hash_value(k) % num_buckets;
const_iterator it = buckets_[bucket].first;
if (it == values_.end())
return it;
const_iterator end = buckets_[bucket].last;
++end;
while (it != end)
{
if (it->first == k)
return it;
++it;
}
return values_.end();
}
// Insert a new entry into the map.
std::pair<iterator, bool> insert(const value_type& v)
{
size_t bucket = calculate_hash_value(v.first) % num_buckets;
iterator it = buckets_[bucket].first;
if (it == values_.end())
{
buckets_[bucket].first = buckets_[bucket].last =
values_.insert(values_.end(), v);
return std::pair<iterator, bool>(buckets_[bucket].last, true);
}
iterator end = buckets_[bucket].last;
++end;
while (it != end)
{
if (it->first == v.first)
return std::pair<iterator, bool>(it, false);
++it;
}
buckets_[bucket].last = values_.insert(end, v);
return std::pair<iterator, bool>(buckets_[bucket].last, true);
}
// Erase an entry from the map.
void erase(iterator it)
{
assert(it != values_.end());
size_t bucket = calculate_hash_value(it->first) % num_buckets;
bool is_first = (it == buckets_[bucket].first);
bool is_last = (it == buckets_[bucket].last);
if (is_first && is_last)
buckets_[bucket].first = buckets_[bucket].last = values_.end();
else if (is_first)
++buckets_[bucket].first;
else if (is_last)
--buckets_[bucket].last;
values_.erase(it);
}
// Remove all entries from the map.
void clear()
{
// Clear the values.
values_.clear();
// Initialise all buckets to empty.
for (size_t i = 0; i < num_buckets; ++i)
buckets_[i].first = buckets_[i].last = values_.end();
}
private:
// The list of all values in the hash map.
std::list<value_type> values_;
// The type for a bucket in the hash table.
struct bucket_type
{
iterator first;
iterator last;
};
// The number of buckets in the hash.
enum { num_buckets = 1021 };
// The buckets in the hash.
bucket_type buckets_[num_buckets];
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_HASH_MAP_HPP

View file

@ -0,0 +1,137 @@
//
// io_control.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_IO_CONTROL_HPP
#define ASIO_DETAIL_IO_CONTROL_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/socket_types.hpp"
namespace asio {
namespace detail {
namespace io_control {
// IO control command for non-blocking I/O.
class non_blocking_io
{
public:
// Default constructor.
non_blocking_io()
: value_(0)
{
}
// Construct with a specific command value.
non_blocking_io(bool value)
: value_(value ? 1 : 0)
{
}
// Get the name of the IO control command.
int name() const
{
return FIONBIO;
}
// Set the value of the I/O control command.
void set(bool value)
{
value_ = value ? 1 : 0;
}
// Get the current value of the I/O control command.
bool get() const
{
return value_ != 0;
}
// Get the address of the command data.
detail::ioctl_arg_type* data()
{
return &value_;
}
// Get the address of the command data.
const detail::ioctl_arg_type* data() const
{
return &value_;
}
private:
detail::ioctl_arg_type value_;
};
// I/O control command for getting number of bytes available.
class bytes_readable
{
public:
// Default constructor.
bytes_readable()
: value_(0)
{
}
// Construct with a specific command value.
bytes_readable(std::size_t value)
: value_(static_cast<detail::ioctl_arg_type>(value))
{
}
// Get the name of the IO control command.
int name() const
{
return FIONREAD;
}
// Set the value of the I/O control command.
void set(std::size_t value)
{
value_ = static_cast<detail::ioctl_arg_type>(value);
}
// Get the current value of the I/O control command.
std::size_t get() const
{
return static_cast<std::size_t>(value_);
}
// Get the address of the command data.
detail::ioctl_arg_type* data()
{
return &value_;
}
// Get the address of the command data.
const detail::ioctl_arg_type* data() const
{
return &value_;
}
private:
detail::ioctl_arg_type value_;
};
} // namespace io_control
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_IO_CONTROL_HPP

Some files were not shown because too many files have changed in this diff Show more