text:
/* Unbindery */
/* -------------------------------------------------- */

var Unbindery = function() {

	// Redirect to dashboard (with optional message or error)
	// --------------------------------------------------

	this.redirectToDashboard = function(message, error) {
		var locStr = app_url + "/users/" + username + "/dashboard";

		// Set the message/error session variables before we redirect
		$.post(app_url + "/messages", { message: message, error: error }, function() {
			window.location.href = locStr;
		});
	};

	// Call the API
	// --------------------------------------------------

	this.callAPI = function(call, method, data, callback) {
		// Prepare the URL
		switch (call) {
			case 'get-new-item':
				if (data.projectType == 'system') {
					url = '/projects/' + data.projectSlug + '/items/get';
				} else {
					url = '/users/' + data.projectOwner + '/projects/' + data.projectSlug + '/items/get';
				}
				break;

			case 'save-transcript':
				if (data.projectType == 'system') {
					url = '/projects/' + data.projectSlug + '/items/' + data.itemId + '/transcript';
				} else {
					url = '/users/' + data.projectOwner + '/projects/' + data.projectSlug + '/items/' + data.itemId + '/transcript';
				}
				break;

			case 'save-project':
			case 'save-project-and-activate':
				if (data.projectType == 'system') {
					url = '/projects/' + data.projectSlug;
				} else {
					url = '/users/' + data.projectOwner + '/projects/' + data.projectSlug;
				}
				break;

			case 'add-items':
				if (data.projectType == 'system') {
					url = '/projects/' + data.projectSlug + '/items';
				} else {
					url = '/users/' + data.projectOwner + '/projects/' + data.projectSlug + '/items';
				}
				break;

			case 'delete-item':
				if (data.projectType == 'system') {
					url = '/projects/' + data.projectSlug + '/items/' + data.itemId + '/delete';
				} else {
					url = '/users/' + data.projectOwner + '/projects/' + data.projectSlug + '/items/' + data.itemId + '/delete';
				}
				break;

			case 'delete-user':
				url = '/users/' + data.username;
				break;

			case 'split-transcript':
				if (data.projectType == 'system') {
					url = '/projects/' + data.projectSlug + '/transcript/split';
				} else {
					url = '/users/' + data.projectOwner + '/projects/' + data.projectSlug + '/transcript/split';
				}
				break;

			case 'import-transcript':
				if (data.projectType == 'system') {
					url = '/projects/' + data.projectSlug + '/import';
				} else {
					url = '/users/' + data.projectOwner + '/projects/' + data.projectSlug + '/import';
				}
				break;

			case 'save-settings':
				url = '/users/' + data.username + '/settings';
				break;

			case 'add-user-to-project':
				if (data.projectType == 'system') {
					url = '/projects/' + data.projectSlug + '/membership';
				} else {
					url = '/users/' + data.projectOwner + '/projects/' + data.projectSlug + '/membership';
				}
				break;

			case 'remove-user-from-project':
				if (data.projectType == 'system') {
					url = '/projects/' + data.projectSlug + '/membership/leave';
				} else {
					url = '/users/' + data.projectOwner + '/projects/' + data.projectSlug + '/membership/leave';
				}
				break;
		}

		switch (method) {
			case 'POST':
				$.post(app_url + url, data, callback, 'json');
				break;

			case 'GET':
				$.get(app_url + url, data, callback, 'json');
				break;

			case 'DELETE':
				$.ajax({
					url: app_url + url,
					type: 'DELETE',
					dataType: 'json',
					success: callback,
					error: callback
				});
				break;
		}
	};

	// Show/hide the spinner
	// --------------------------------------------------

	this.showSpinner = function(id) {
		if (typeof id === 'undefined') id = '#spinner';

		$(id).show();
	};

	this.hideSpinner = function(id) {
		if (typeof id === 'undefined') id = '#spinner';

		$(id).hide();
	};

	// Insert a character from the character pad
	// --------------------------------------------------

	this.insertText = function(text) {
		// Insert the character into the text box
		var textbox = $("textarea#transcript");
		textbox.append(text);
	};

	// Get a new item
	// --------------------------------------------------

	this.getNewItem = function(projectSlug, projectOwner, projectType, actionType) {
		// Get the username
		var username = $("#username").html();

		this.callAPI('get-new-item', 'POST', { projectSlug: projectSlug, projectOwner: projectOwner, projectType: projectType, username: username, type: actionType },
			function(data) {
				if (data.status == true) {
					if (projectType == 'system') {
						var locStr = app_url + '/projects/' + projectSlug + '/items/' + data.code + '/' + actionType;
					} else {
						var locStr = app_url + '/users/' + projectOwner + '/projects/' + projectSlug + '/items/' + data.code + '/' + actionType;
					}

					window.location.href = locStr;
				} else {
					unbindery.hideSpinner();

					// Set up error code
					errorCode = "error." + data.code.replace(/-/, "_");

					unbindery.redirectToDashboard("", errorCode);
				}
			}
		);

		return false;
	};

	// Save transcript
	// --------------------------------------------------

	this.saveTranscript = function(isDraft, isReview, getAnother) {
		unbindery.showSpinner();

		var itemId = $("#item_id").val();
		var projectSlug = $("#project_slug").val();
		var username = $("#username").html();
		var transcript = $("#transcript").val();
		var projectOwner = $("#project_owner").val();
		var proofUser = $("#proof_user").val();
		var proofType = $("#proof_type").val();

		var projectType = 'system';
		if (projectOwner != '') projectType = 'user';

		var status = 'completed';
		if (isDraft) status = 'draft';
		if (isReview) status = 'reviewed';

		// Get any fields and serialize them
		var fields = {};
		$("#fields_container [id^='fields_']").each(function() {
			// Get the type (text, dropdown, checkbox, radio)
			var type = ($(this).prop("tagName") == "SELECT") ? "dropdown" : $(this).attr("type");

			// And the ID, which we use as the key
			var key = $(this).attr("data-id");

			// Get the value
			var value = '';
			switch (type) {
				case 'text':
					value = $(this).val().trim();
					break;

				case 'dropdown':
					value = $(this).find("option:selected").val();
					break;

				case 'radio':
					value = ($(this).attr('checked')) ? $(this).val() : '';
					break;

				case 'checkbox':
					value = ($(this).attr('checked')) ? true : false;
					break;
			}

			// Special case for radio buttons
			if (typeof fields[key] == 'undefined' || (fields[key] == '' && value != '')) {
				fields[key] = value;
			}
		});

		// Save
		unbindery.callAPI('save-transcript', 'POST', { itemId: itemId, projectSlug: projectSlug, projectOwner: projectOwner, projectType: projectType, username: username, draft: isDraft, proofType: proofType, proofUser: proofUser, transcript: transcript, fields: JSON.stringify(fields), status: status },
			function(data) {
				if (data.statuscode == "success") {
					if (getAnother) {
						// And get the new item
						var projectSlug = $('#project_slug').val();
						var projectOwner = $('#project_owner').val();
						var projectType = $('#project_type').val();

						unbindery.getNewItem(projectSlug, projectOwner, projectType, proofType);
					} else {
						unbindery.redirectToDashboard("", "");
					}

					unbindery.hideSpinner();
				} else {
					unbindery.redirectToDashboard("", "error.saving_transcript");
				}
			});
	};

	// Save project
	// --------------------------------------------------

	this.saveProject = function() {
		unbindery.showSpinner();

		var projectSlug = $("#project_slug").val();
		var projectType = $("#project_type").val();
		var projectOwner = $("#project_owner").val().trim();
		var projectName = $("#project_name").val().trim();
		var projectStatus = $("#project_status").val().trim();
		var projectPublic = ($("#project_public").val() == 'public') ? 1 : 0;
		var projectDesc = $("#project_desc").val().trim();
		var projectLang = $("#project_lang").val().trim();
		var projectWorkflow = $("#project_workflow").val().trim();
		var projectDownloadTemplate = $("#project_download_template").val().trim();
		var projectCharacters = $("#project_characters").val().trim();
		var projectFields = $("#project_fields").val().trim();

		unbindery.callAPI('save-project', 'POST', { projectSlug: projectSlug, projectType: projectType, projectOwner: projectOwner, projectName: projectName, projectStatus: projectStatus, projectPublic: projectPublic, projectDesc: projectDesc, projectLang: projectLang, projectWorkflow: projectWorkflow, projectDownloadTemplate: projectDownloadTemplate, projectCharacters: projectCharacters, projectFields: projectFields },
			function(data) {
				if (data.statuscode == "success") {
					unbindery.hideSpinner();
					unbindery.redirectToDashboard("admin.project.saved", "");
				} else {
					unbindery.redirectToDashboard("", "error.saving_project");
				}
			});
	};

	// Add items to a project after they've been uploaded
	// --------------------------------------------------

	this.addItemsToProject = function(fileList) {
		var projectSlug = $("#project_slug").val();
		var projectType = $("#project_type").val();

		unbindery.showSpinner('#uploadspinner');

		this.callAPI('add-items', 'POST', { projectSlug: projectSlug, projectType: projectType, fileList: fileList },
			function(data) {
				if (data.status == 'success') {
					unbindery.hideSpinner('#uploadspinner');

					// If success, add items to item list
					for (item in data.items) {
						item = data.items[item];

						html = "
";
						html += "";
						html +=		"×";
						html += "";
						html += "" + item.title + "";
						html += " available";
						html += "
";

						$(html).appendTo($("section.items ul.items"));
					}

					// Also remove the items from the queue
					fileList = [];
					$("#file_uploadQueue").html('');
				}
			}
		);
	};

	// Delete an item
	// --------------------------------------------------

	this.deleteItem = function(itemId) {
		var projectSlug = $("#project_slug").val();
		var projectType = $("#project_type").val();

		this.callAPI('delete-item', 'POST', { projectSlug: projectSlug, projectType: projectType, itemId: itemId },
			function(data) {
				if (data.status == 'success') {
					$("ul.items li[data-id=" + itemId + "]").remove();
				}
			}
		);
	};

	// Delete a user
	// --------------------------------------------------

	this.deleteUser = function(username) {
		this.callAPI('delete-user', 'DELETE', { username: username },
			function(data) {
				if (data.status == 'success') {
					$("ul.items.users li[data-username=" + username + "]").remove();
				}
			}
		);
	};

	// Add a user/role to a project
	// --------------------------------------------------

	this.addUserToProject = function(username, role) {
		var projectSlug = $("#project_slug").val();
		var projectType = $("#project_type").val();
		var projectOwner = $("#project_owner").val();

		this.callAPI('add-user-to-project', 'POST', { username: username, role: role, projectSlug: projectSlug, projectType: projectType, projectOwner: projectOwner },
			function(data) {
				if (data.status == 'success') {
					$("
×" + username + ": " + role + "
").appendTo("ul.items.members");

					// Clear out to defaults
					$(".addbox input[type=text]").val('');
					$(".addbox select").val("proofer");
				}
			}
		);
	}

	// Remove a user/role from a project
	// --------------------------------------------------

	this.removeUserFromProject = function(username, role) {
		var projectSlug = $("#project_slug").val();
		var projectType = $("#project_type").val();
		var projectOwner = $("#project_owner").val();

		this.callAPI('remove-user-from-project', 'POST', { username: username, role: role, projectSlug: projectSlug, projectType: projectType, projectOwner: projectOwner },
			function(data) {
				if (data.status == 'success') {
					$("ul.items.members li[data-username='" + username + "'][data-role='" + role + "']").remove();
				}
			}
		);
	}

	// Update the import preview (project admin page)
	// --------------------------------------------------

	this.updateImportPreview = function() {
		var template = $("#import-template").val();
		var transcript = $("#import-transcript").val().trim();
		var projectSlug = $("#project_slug").val();
		var projectType = $("#project_type").val();
		var projectOwner = $("#project_owner").val();

		if (template == '' || transcript == '') return;

		this.callAPI('split-transcript', 'POST', { template: template, transcript: transcript, projectType: projectType, projectOwner: projectOwner, projectSlug: projectSlug },
			function(data) {
				if (data.status == 'success') {
					$("#preview-header").html("Preview (" + data.transcripts.length + " items)");

					var html = '';
					for (i=0; i<data.transcripts.length; i++) {
						html += "
";
						html += $(".sidebar .items li:nth-child(" + (i + 1) + ")").find("a:not(.delete)").html();
						html += ": " + data.transcripts[i] + "
";
					}
					$("#import-preview").html(html);

					// Make sure the # of items matches
					if ($("#import-preview p").length != $(".sidebar ul.items li").length) {
						html = "
";
						html += "Number of items doesn't match up."; // TODO: get from translations
						html += "
";

						$(html).prependTo("#main.import .sidebar");
						return false;
					}
				}
			}
		);
	};

	// Import a transcript
	// --------------------------------------------------

	this.importTranscript = function() {
		var template = $("#import-template").val();
		var transcript = $("#import-transcript").val().trim();
		var projectSlug = $("#project_slug").val();
		var projectType = $("#project_type").val();
		var projectOwner = $("#project_owner").val();

		if (template == '' || transcript == '') return;

		// Make sure the # of items matches
		if ($("#import-preview p").length != $(".sidebar ul.items li").length) {
			return false;
		}

		// Create array of item IDs
		items = [];
		$(".sidebar ul.items li").each(function() {
			items.push($(this).attr("data-id"));
		});

		this.callAPI('import-transcript', 'POST', { template: template, transcript: transcript, projectType: projectType, projectOwner: projectOwner, projectSlug: projectSlug, items: items },
			function(data) {
				if (data.status == 'success') {
					// Redirect to project admin page
					if (projectType == 'system') {
						var locStr = app_url + '/projects/' + projectSlug + '/admin';
					} else {
						var locStr = app_url + '/users/' + projectOwner + '/projects/' + projectSlug + '/admin';
					}

					window.location.href = locStr;
				}
			}
		);
	};

	// Save a user's settings
	// --------------------------------------------------

	this.saveSettings = function() {
		unbindery.showSpinner();

		var username = $("#username").html();
		var name = $("#user_name").val().trim();
		var email = $("#user_email").val().trim();

		var prefs = {
			'sidebyside': ($("#sidebyside").attr("checked")) ? 1 : 0,
			'theme': $("#theme").find("option:selected").val()
		};

		// Loop through notifications and add
		prefs.notifications = {};
		$(".notifications input[type=checkbox]").each(function() {
			prefs.notifications[$(this).attr("name")] = ($(this).attr("checked")) ? 1 : 0;
		});

		unbindery.callAPI('save-settings', 'POST', { username: username, name: name, email: email, prefs: prefs },
			function(data) {
				if (data.statuscode == "success") {
					unbindery.hideSpinner();
					unbindery.redirectToDashboard("settings.saved", "");
				} else {
					unbindery.redirectToDashboard("", "settings.error");
				}
			}
		);
	};

}

$(document).ready(function() {
	unbindery = new Unbindery();

	// Click handlers for the buttons
	// --------------------------------------------------

	$("#action-save-draft").click(function() {
		isReview = ($("#transcript_type").val() == 'review') ? true : false;
		unbindery.saveTranscript(true, isReview, false);		// yes draft, review depends, don't get another
		return false;
	});

	$("#action-finish, #action-save-changes").click(function(e) {
		isReview = ($("#transcript_type").val() == 'review') ? true : false;
		unbindery.saveTranscript(false, isReview, false);		// no draft, review depends, don't get another
		return false;
	});

	$("#action-finish-continue").click(function(e) {
		isReview = ($("#transcript_type").val() == 'review') ? true : false;
		unbindery.saveTranscript(false, isReview, true);		// no draft, review depends, do get another one
		return false;
	});

	$("#action-save-project").click(function(e) {
		unbindery.saveProject();
	});

	$("#action-save-project-and-activate").click(function(e) {
		// Set to active first
		$("#project_status").val("active");

		// And now save the project as usual
		unbindery.saveProject();
	});

	// Click handler for getting a new item
	// --------------------------------------------------

	$(".getnewitem").click(function(e) {
		// Hide the button (so we don't click it again)
		$(this).hide();

		// Show the spinner
		$(this).siblings('.spinner').show();

		// And get the new page
		var projectSlug = this.getAttribute('data-project-slug');
		var projectOwner = this.getAttribute('data-project-owner');
		var projectType = this.getAttribute('data-project-type');
		var actionType = ($(this).parents("ul.action_list").hasClass("proof")) ? 'proof' : 'review';

		unbindery.getNewItem(projectSlug, projectOwner, projectType, actionType);
	});

	// Install page
	// --------------------------------------------------

	$("#install_form input[type=submit]").click(function() {
		if ($(this).siblings("#username").val().trim() == '') {
			$(this).siblings("#error").show();
			return false;
		}

		if ($(this).siblings("#password").length > 0 && $(this).siblings("#password").val().trim() == '') {
			$(this).siblings("#error").show();
			return false;
		}
	});

	// Project page (joining/leaving)
	// --------------------------------------------------

	$('.proj_details .membership a').click(function() {
		// The URL to call
		var url = ($(this).hasClass('join')) ? $(this).attr('href') : $(this).attr('href') + '/leave';

		var message = ($(this).hasClass('join')) ? 'You are now a member of this project.' : 'You have left this project.';

		// call URL with appropriate method
		$.ajax({
			url: url,
			type: 'POST',
			dataType: 'json',
			success: function(data) {
				$(".proj_details .membership a").slideUp(50, function() {
					$("
" + message + "
").appendTo(".proj_details .membership");
				});
			},
			error: function(data) {
				$(".proj_details .membership a").slideUp(50, function() {
					$("
Error connecting to web service. Contact the administrator.
").appendTo(".proj_details .membership");
				});
			}
		});

		return false;
	});

	// Item deletion (project admin page)
	// --------------------------------------------------

	$("#main.add section.items ul.items").on("click", "a.delete", function() {
		var itemId = $(this).parents("li:first").attr("data-id");

		if (confirm("Are you sure you want to delete that item?")) {
			unbindery.deleteItem(itemId);
		}

		return false;
	});

	// Adding users to projects (project admin page)
	// --------------------------------------------------

	$("#main.add .addbox input[type=submit]").on("click", function() {
		var username = $(".addbox input[type=text]").val().trim();
		var role = $(".addbox select option:selected").val();

		unbindery.addUserToProject(username, role);

		return false;
	});

	// Removing users from projects (project admin page)
	// --------------------------------------------------

	$("#main.add ul.items.members").on("click", "a.delete", function() {
		var username = $(this).parents("li:first").attr("data-username");
		var role = $(this).parents("li:first").attr("data-role");

		if (confirm("Are you sure you want to remove that user from this project?")) {
			unbindery.removeUserFromProject(username, role);
		}

		return false;
	});

	// Character pad
	// --------------------------------------------------

	$("#controls #characters").on("click", function() {
		$("#characterpad").toggle();

		return false;
	});

	$("#characterpad li").on("click", function() {
		var character = $(this).html();

		unbindery.insertText(character);

		return false;
	});

	// Import transcript page
	// --------------------------------------------------

	$(".import #import-template").on("change", function() {
		unbindery.updateImportPreview();
	});

	$(".import #import-transcript").on("change", function() {
		unbindery.updateImportPreview();
	});

	$("#action-import-transcript").on("click", function() {
		unbindery.importTranscript();
		return false;
	});

	$("#main.import .sidebar ul.items").on("click", "li .itemcontrols a.delete", function() {
		var parentList = $(this).parents("ul:first");

		$(this).parents("li:first").remove();

		parentList.siblings("h3").html("Selected Items (" + parentList.find("li").length + " items)");

		// Make sure the # of items matches
		if ($("#import-preview p").length != $(".sidebar ul.items li").length) {
			html = "
";
			html += "Number of items doesn't match up."; // TODO: get from translations
			html += "
";

			$(html).prependTo("#main.import .sidebar");
		} else {
			$(".sidebar div.error").remove();
		}

		return false;
	});

	// User settings page
	// --------------------------------------------------

	$("#action-save-settings").click(function() {
		unbindery.saveSettings();
	});

	// Deleting users (admin dashboard)
	// --------------------------------------------------

	$("#main.dashboard ul.items.users").on("click", "li .itemcontrols a.delete", function() {
		var username = $(this).parents("li:first").find("b").html();

		if (confirm("Are you sure you want to delete that user?")) {
			unbindery.deleteUser(username);
		}

		return false;
	});
});


text:
package com.app.nfsclient.protocol.xfile;

import java.io.IOException;

/**
 * The XFileAccessor interface is implemented by filesystems that
 * need to be accessed via the XFile API.
 *
 * Classes that implement this interface must be associated
 * with a URL scheme that is structured according to the
 * Common Internet Scheme syntax described in
 * RFC 1738;
 * an optional location part followed by a hierarchical set
 * of slash separated directories.
 *

 * A class file that implements this interface must be named
 * "XFileAccessor" and be installed in a directory named after
 * the URL scheme that it implements, for instance, an XFileAccessor
 * that provides file access through the HTTP protocol would be
 * associated with the "http" URL and its class file would be
 * called:
 *

 * 	http.XFileAccessor
 *

 * A class prefix is added to this name.  The default prefix is
 * com.sun and this composite name is located by the
 * classLoader via the CLASSPATH.
 * For instance, Sun's "nfs" XFileAccessor is installed as:
 *

 * 	com.sun.nfs.XFileAccessor
 *

 * The default class prefix com.sun can be changed by
 * setting the System property java.protocol.xfile
 * to any desired prefix or a list of prefixes separated by
 * vertical bars. Each prefix in the list will be used to
 * construct a package name and the classLoader will attempt
 * to load that package via the CLASSPATH.  This process will
 * continue until the XFileAccessor is successfully loaded.
 *

 * For instance, if you want to use the "ftp"
 * XFileAccessor from Acme, Inc and the "nfs" XFileAccessor
 * from "ABC Inc." then you can set the system property as
 * follows:
 *

 * 	java.protocol.xfile=com.acme|com.abc
 *

 * When an "ftp" URL is used, the following package names will
 * be constructed:
 * <code

 *    com.acme.ftp.XFileAccessor
 *    com.abc.ftp.XFileAccessor
 *    com.sun.ftp.XFileAccessor
 *

 * (the default "com.sun" prefix is automatically added to
 * the end of the property list)
 *

 * The class loader attempts to load each of the constructed
 * package names in turn relative to the CLASSPATH until it is
 * successful.
 *

 * A subsequent reference to an "nfs" URL will result in
 * the following list of candidate package names:
 * <code

 *    com.acme.nfs.XFileAccessor
 *    com.abc.nfs.XFileAccessor
 *    com.sun.nfs.XFileAccessor
 *

 * In this case the "nfs" XFileAccessor from ABC, Inc. will
 * be loaded in preference to Sun's NFS.
 *
 *
 * @author  Brent Callaghan
 * @version 1.0, 04/08/98
 * @see     com.sun.xfile.XFile
 */
public interface XFileAccessor {

    /**
     * Open a file in this filesystem.
     *
     * This method is called before any other method.
     * It may be used to open the real file.
     *
     * @param xf The XFile for the file to be accessed
     * 		The URL will be of the form
     *

     * 		    <proto>://<location>/<path>
     *

     * 		where <proto> is the name of the filesystem,
     *		e.g. "nfs" and <location> is the location of
     *		the filesystem.  For nfs this is the network name of
     *		a server.  The <path> is a pathname that locates
     *		the file within <location>. As required by
     *		RFC 1738, the component delimiters in the pathname
     *		are as for URL syntax: forward slashes only.
     * @param serial true if serial access; false if random access
     * @param readOnly true if read only; false if read/write
     */
    boolean open(XFile xf, boolean serial, boolean readOnly);

    /**
     *  Return the XFile for this Accessor
     */
    XFile getXFile();

    /**
     * Tests if this XFile object exists.
     *
     * @return true if the file specified by this object
     *         exists; false otherwise.
     */
    boolean exists();

    /**
     * Tests if the application can write to this file.
     *
     * @return true if the application is allowed to
     *         write to a file whose name is specified by this
     *         object; false otherwise.
     */
    boolean canWrite();

    /**
     * Tests if the application can read from the specified file.
     *
     * @return true if the file specified by this
     *         object exists and the application can read the file;
     *         false otherwise.
     */
    boolean canRead();

    /**
     * Tests if the file represented by this
     * object is a "normal" file.
     *

     * A file is "normal" if it is not a directory and, in
     * addition, satisfies other system-dependent criteria. Any
     * non-directory file created by a Java application is
     * guaranteed to be a normal file.
     *
     * @return true if the file specified by this
     *         object exists and is a "normal"
     *         file; false otherwise.
     */
    boolean isFile();

    /**
     * Tests if the file represented by this XFileAccessor
     * object is a directory.
     *
     * @return true if this XFileAccessor object
     *         exists and is a directory; false
     *         otherwise.
     */
    boolean isDirectory();

    /**
     * Returns the time that the file represented by this
     * XFile object was last modified.
     * It is measured as the time in milliseconds since
     * midnight, January 1, 1970 UTC.
     *

     * @return the time the file specified by this object was last
     *         modified, or 0L if the specified file
     *         does not exist.
     */
    long lastModified();

    /**
     * Returns the length of the file represented by this
     * XFileAccessor object.
     *
     * @return the length, in bytes, of the file specified by
     *         this object, or 0L if the specified
     *         file does not exist.
     */
    long length();

    /**
     * Creates an empty file whose pathname is specified by this
     * XFileAccessor object.
     *
     * @return true if the file was created;
     *         false otherwise.
     */
    boolean mkfile();

    /**
     * Creates a directory whose pathname is specified by this
     * XFileAccessor object.
     *
     * @return true if the directory could be created;
     *         false otherwise.
     */
    boolean mkdir();

    /**
     * Renames the file specified by this XFileAccessor object to
     * have the pathname given by the XFileAccessor object argument.
     *
     * The destination XFile object will be of the same URL
     * scheme as this object. The change of name must not
     * affect the existence or accessibility of this object.
     *
     * @param  dest the new filename.
     * @return true if the renaming succeeds;
     *         false otherwise.
     */
    boolean renameTo(XFile dest);

    /**
     * Deletes the file specified by this object.  If the target
     * file to be deleted is a directory, it must be empty for deletion
     * to succeed.
     *
     * @return     true if the file is successfully deleted;
     *             false otherwise.
     */
    boolean delete();

    /**
     * Returns a list of the files in the directory specified by
     * this XFileAccessor object.
     *
     * @return an array of file names in the specified directory.
     *         This list does not include the current directory or
     *         the parent directory ("." and
     *         ".." on Unix systems).
     */
    String[] list();

    /**
     * Reads a subarray as a sequence of bytes.
     *
     * @param b the buffer into which the data is read
     * @param off the start offset in the data buffer
     * @param len the maximum number of bytes to be read
     * @param foff the offset into the file
     * @return number of bytes read - zero if none.
     * @exception java.io.IOException If an I/O error has occurred.
     */
    int read(byte b[], int off, int len, long foff) throws IOException;

    /**
     * Writes a sub array as a sequence of bytes.
     *
     * @param b the data to be written
     * @param off the start offset in the data in the buffer
     * @param len the number of bytes that are written
     * @param foff the offset into the file
     * @exception java.io.IOException If an I/O error has occurred.
     */
    void write(byte b[], int off, int len, long foff) throws IOException;

    /**
     * Forces any buffered output bytes to be written out.
     *

     *
     * @exception  java.io.IOException  if an I/O error occurs.
     */
    void flush() throws IOException;

    /**
     * Close the file.
     *
     * Closes this file and releases any system resources
     * associated with the file.
     *
     * After the file is closed further I/O operations may
     * throw IOException.
     *
     * @exception java.io.IOException If an I/O error has occurred.
     */
    void close() throws IOException;
}

redpajama_set_name: RedPajamaGithub


text:
package sun.jvm.hotspot.jdi;

import java.io.*;
import com.sun.jdi.*;

import sun.jvm.hotspot.debugger.Address;
import sun.jvm.hotspot.debugger.OopHandle;
import sun.jvm.hotspot.oops.Oop;
import sun.jvm.hotspot.oops.Mark;
import sun.jvm.hotspot.oops.Instance;
import sun.jvm.hotspot.oops.Array;
import sun.jvm.hotspot.oops.OopUtilities;
import sun.jvm.hotspot.oops.Klass;
import sun.jvm.hotspot.oops.DefaultHeapVisitor;
import sun.jvm.hotspot.runtime.JavaThread;
import sun.jvm.hotspot.runtime.JavaVFrame;
import sun.jvm.hotspot.runtime.MonitorInfo;
import sun.jvm.hotspot.runtime.ObjectMonitor;
import sun.jvm.hotspot.runtime.Threads;
import sun.jvm.hotspot.utilities.Assert;

import java.util.*;

public class ObjectReferenceImpl extends ValueImpl implements ObjectReference {
    private Oop  saObject;
    private long myID;
    private boolean monitorInfoCached = false;
    private ThreadReferenceImpl owningThread = null;
    private List waitingThreads = null; // List<ThreadReferenceImpl>
    private int entryCount = 0;

    private static long nextID = 0L;
    private static synchronized long nextID() {
        return nextID++;
    }

    ObjectReferenceImpl(VirtualMachine aVm, sun.jvm.hotspot.oops.Oop oRef) {
        super(aVm);
        saObject = oRef;
        myID = nextID();
    }

    protected Oop ref() {
        return saObject;
    }

    public Type type() {
        return referenceType();
    }

    public ReferenceType referenceType() {
        Klass myKlass = ref().getKlass();
        return vm.referenceType(myKlass);
    }

    public Value getValue(Field sig) {
        List list = new ArrayList(1);
        list.add(sig);
        Map map = getValues(list);
        return(Value)map.get(sig);
    }

    public Map getValues(List theFields) {
        //validateMirrors(theFields);

        List staticFields = new ArrayList(0);
        int size = theFields.size();
        List instanceFields = new ArrayList(size);

        for (int i=0; i<size; i++) {
            sun.jvm.hotspot.jdi.FieldImpl field =
                (sun.jvm.hotspot.jdi.FieldImpl)theFields.get(i);

            // Make sure the field is valid
            ((ReferenceTypeImpl)referenceType()).validateFieldAccess(field);

            // FIX ME! We need to do some sanity checking
            // here; make sure the field belongs to this
            // object.
            if (field.isStatic()) {
                staticFields.add(field);
            } else {
                instanceFields.add(field);
            }
        }

        // Look up static field(s) first to mimic the JDI implementation
        Map map;
        if (staticFields.size() > 0) {
            map = referenceType().getValues(staticFields);
        } else {
            map = new HashMap(size);
        }

        // Then get instance field(s)
        size = instanceFields.size();
        for (int ii=0; ii<size; ii++){
            FieldImpl fieldImpl = (FieldImpl)instanceFields.get(ii);
            map.put(fieldImpl, fieldImpl.getValue(saObject));
        }

        return map;
    }

    public void setValue(Field field, Value value)
                   throws InvalidTypeException, ClassNotLoadedException {
        vm.throwNotReadOnlyException("ObjectReference.setValue(...)");
    }

    public Value invokeMethod(ThreadReference threadIntf, Method methodIntf,
                              List arguments, int options)
                              throws InvalidTypeException,
                                     IncompatibleThreadStateException,
                                     InvocationException,
                                     ClassNotLoadedException {
        vm.throwNotReadOnlyException("ObjectReference.invokeMethod(...)");
        return null;
    }

    public void disableCollection() {
        vm.throwNotReadOnlyException("ObjectReference.disableCollection()");
    }

    public void enableCollection() {
        vm.throwNotReadOnlyException("ObjectReference.enableCollection()");
    }

    public boolean isCollected() {
        vm.throwNotReadOnlyException("ObjectReference.isCollected()");
        return false;
    }

    public long uniqueID() {
        return myID;
    }

    public List waitingThreads() throws IncompatibleThreadStateException {
        if (vm.canGetMonitorInfo() == false) {
            throw new UnsupportedOperationException();
        }

        if (! monitorInfoCached) {
            computeMonitorInfo();
        }
        return waitingThreads;
    }

    public ThreadReference owningThread() throws IncompatibleThreadStateException {
        if (vm.canGetMonitorInfo() == false) {
            throw new UnsupportedOperationException();
        }

        if (! monitorInfoCached) {
            computeMonitorInfo();
        }
        return owningThread;
    }

    public int entryCount() throws IncompatibleThreadStateException {
        if (vm.canGetMonitorInfo() == false) {
            throw new UnsupportedOperationException();
        }

        if (! monitorInfoCached) {
            computeMonitorInfo();
        }
        return entryCount;
    }

    // new method since 1.6.
    // Real body will be supplied later.
    public List referringObjects(long maxReferrers) {
        if (!vm.canGetInstanceInfo()) {
            throw new UnsupportedOperationException(
                      "target does not support getting instances");
        }
        if (maxReferrers < 0) {
            throw new IllegalArgumentException("maxReferrers is less than zero: "
                                              + maxReferrers);
        }
        final ObjectReference obj = this;
        final List objects = new ArrayList(0);
        final long max = maxReferrers;
                vm.saObjectHeap().iterate(new DefaultHeapVisitor() {
                private long refCount = 0;
                public boolean doObj(Oop oop) {
                                        try {
                                                ObjectReference objref = vm.objectMirror(oop);
                                                List fields = objref.referenceType().allFields();
                                                for (int i=0; i < fields.size(); i++) {
                                                        Field fld = (Field)fields.get(i);
                                                        if (objref.getValue(fld).equals(obj) && !objects.contains(objref)) {
                                                                objects.add(objref);
                                                                refCount++;
                                                        }
                                                }
                                                if (max > 0 && refCount >= max) {
                                                        return true;
                                                }
                                        } catch  (RuntimeException x) {
                                          // Ignore RuntimeException thrown from vm.objectMirror(oop)
                                          // for bad oop. It is possible to see some bad oop
                                          // because heap might be iterating at no safepoint.
                                        }
                                        return false;

                }
            });
        return objects;
    }

    // refer to JvmtiEnvBase::count_locked_objects.
    // Count the number of objects for a lightweight monitor. The obj
    // parameter is object that owns the monitor so this routine will
    // count the number of times the same object was locked by frames
    // in JavaThread. i.e., we count total number of times the same
    // object is (lightweight) locked by given thread.
    private int countLockedObjects(JavaThread jt, Oop obj) {
        int res = 0;
        JavaVFrame frame = jt.getLastJavaVFrameDbg();
        while (frame != null) {
            List monitors = frame.getMonitors();
            OopHandle givenHandle = obj.getHandle();
            for (Iterator itr = monitors.iterator(); itr.hasNext();) {
                MonitorInfo mi = (MonitorInfo) itr.next();
                if (mi.eliminated() && frame.isCompiledFrame()) continue; // skip eliminated monitor
                if (givenHandle.equals(mi.owner())) {
                    res++;
                }
            }
            frame = (JavaVFrame) frame.javaSender();
        }
        return res;
    }

    // wrappers on same named method of Threads class
    // returns List<JavaThread>
    private List getPendingThreads(ObjectMonitor mon) {
        return vm.saVM().getThreads().getPendingThreads(mon);
    }

    // returns List<JavaThread>
    private List getWaitingThreads(ObjectMonitor mon) {
        return vm.saVM().getThreads().getWaitingThreads(mon);
    }

    private JavaThread owningThreadFromMonitor(Address addr) {
        return vm.saVM().getThreads().owningThreadFromMonitor(addr);
    }

    // refer to JvmtiEnv::GetObjectMonitorUsage
    private void computeMonitorInfo() {
        monitorInfoCached = true;
        Mark mark = saObject.getMark();
        ObjectMonitor mon = null;
        Address owner = null;
        // check for heavyweight monitor
        if (! mark.hasMonitor()) {
            // check for lightweight monitor
            if (mark.hasLocker()) {
                owner = mark.locker().getAddress(); // save the address of the Lock word
            }
            // implied else: no owner
        } else {
            // this object has a heavyweight monitor
            mon = mark.monitor();

            // The owner field of a heavyweight monitor may be NULL for no
            // owner, a JavaThread * or it may still be the address of the
            // Lock word in a JavaThread's stack. A monitor can be inflated
            // by a non-owning JavaThread, but only the owning JavaThread
            // can change the owner field from the Lock word to the
            // JavaThread * and it may not have done that yet.
            owner = mon.owner();
        }

        // find the owning thread
        if (owner != null) {
            owningThread = vm.threadMirror(owningThreadFromMonitor(owner));
        }

        // compute entryCount
        if (owningThread != null) {
            if (owningThread.getJavaThread().getAddress().equals(owner)) {
                // the owner field is the JavaThread *
                if (Assert.ASSERTS_ENABLED) {
                    Assert.that(false, "must have heavyweight monitor with JavaThread * owner");
                }
                entryCount = (int) mark.monitor().recursions() + 1;
            } else {
                // The owner field is the Lock word on the JavaThread's stack
                // so the recursions field is not valid. We have to count the
                // number of recursive monitor entries the hard way.
                entryCount = countLockedObjects(owningThread.getJavaThread(), saObject);
            }
        }

        // find the contenders & waiters
        waitingThreads = new ArrayList();
        if (mon != null) {
            // this object has a heavyweight monitor. threads could
            // be contenders or waiters
            // add all contenders
            List pendingThreads = getPendingThreads(mon);
            // convert the JavaThreads to ThreadReferenceImpls
            for (Iterator itrPend = pendingThreads.iterator(); itrPend.hasNext();) {
                waitingThreads.add(vm.threadMirror((JavaThread) itrPend.next()));
            }

            // add all waiters (threads in Object.wait())
            // note that we don't do this JVMTI way. To do it JVMTI way,
            // we would need to access ObjectWaiter list maintained in
            // ObjectMonitor::_queue. But we don't have this struct exposed
            // in vmStructs. We do waiters list in a way similar to getting
            // pending threads list
            List objWaitingThreads = getWaitingThreads(mon);
            // convert the JavaThreads to ThreadReferenceImpls
            for (Iterator itrWait = objWaitingThreads.iterator(); itrWait.hasNext();) {
                waitingThreads.add(vm.threadMirror((JavaThread) itrWait.next()));
            }
        }
    }

    public boolean equals(Object obj) {
        if ((obj != null) && (obj instanceof ObjectReferenceImpl)) {
            ObjectReferenceImpl other = (ObjectReferenceImpl)obj;
            return (ref().equals(other.ref())) &&
                   super.equals(obj);
        } else {
            return false;
        }
    }

    public int hashCode() {
        return saObject.hashCode();
    }

    public String toString() {
        return  "instance of " + referenceType().name() + "(id=" + uniqueID() + ")";
    }
}


text:
#if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_EDITOR
/**
 * Autogenerated by Thrift Compiler ()
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Thrift;
using Thrift.Collections;
using System.Runtime.Serialization;
using Thrift.Protocol;
using Thrift.Transport;

namespace GetSocialSdk.Core
{

  #if !SILVERLIGHT
  [Serializable]
  #endif
  public partial class THCompanyProperties : TBase
  {
    private string _enforceSsoProvider;
    private bool _disabled;
    private string _paymentReauthLink;

    public string EnforceSsoProvider
    {
      get
      {
        return _enforceSsoProvider;
      }
      set
      {
        __isset.enforceSsoProvider = true;
        this._enforceSsoProvider = value;
      }
    }

    public bool Disabled
    {
      get
      {
        return _disabled;
      }
      set
      {
        __isset.disabled = true;
        this._disabled = value;
      }
    }

    public string PaymentReauthLink
    {
      get
      {
        return _paymentReauthLink;
      }
      set
      {
        __isset.paymentReauthLink = true;
        this._paymentReauthLink = value;
      }
    }

    public Isset __isset;
    #if !SILVERLIGHT
    [Serializable]
    #endif
    public struct Isset {
      public bool enforceSsoProvider;
      public bool disabled;
      public bool paymentReauthLink;
    }

    public THCompanyProperties() {
    }

    public void Read (TProtocol iprot)
    {
      iprot.IncrementRecursionDepth();
      try
      {
        TField field;
        iprot.ReadStructBegin();
        while (true)
        {
          field = iprot.ReadFieldBegin();
          if (field.Type == TType.Stop) {
            break;
          }
          switch (field.ID)
          {
            case 1:
              if (field.Type == TType.String) {
                EnforceSsoProvider = iprot.ReadString();
              } else {
                TProtocolUtil.Skip(iprot, field.Type);
              }
              break;
            case 2:
              if (field.Type == TType.Bool) {
                Disabled = iprot.ReadBool();
              } else {
                TProtocolUtil.Skip(iprot, field.Type);
              }
              break;
            case 3:
              if (field.Type == TType.String) {
                PaymentReauthLink = iprot.ReadString();
              } else {
                TProtocolUtil.Skip(iprot, field.Type);
              }
              break;
            default:
              TProtocolUtil.Skip(iprot, field.Type);
              break;
          }
          iprot.ReadFieldEnd();
        }
        iprot.ReadStructEnd();
      }
      finally
      {
        iprot.DecrementRecursionDepth();
      }
    }

    public void Write(TProtocol oprot) {
      oprot.IncrementRecursionDepth();
      try
      {
        TStruct struc = new TStruct("THCompanyProperties");
        oprot.WriteStructBegin(struc);
        TField field = new TField();
        if (EnforceSsoProvider != null && __isset.enforceSsoProvider) {
          field.Name = "enforceSsoProvider";
          field.Type = TType.String;
          field.ID = 1;
          oprot.WriteFieldBegin(field);
          oprot.WriteString(EnforceSsoProvider);
          oprot.WriteFieldEnd();
        }
        if (__isset.disabled) {
          field.Name = "disabled";
          field.Type = TType.Bool;
          field.ID = 2;
          oprot.WriteFieldBegin(field);
          oprot.WriteBool(Disabled);
          oprot.WriteFieldEnd();
        }
        if (PaymentReauthLink != null && __isset.paymentReauthLink) {
          field.Name = "paymentReauthLink";
          field.Type = TType.String;
          field.ID = 3;
          oprot.WriteFieldBegin(field);
          oprot.WriteString(PaymentReauthLink);
          oprot.WriteFieldEnd();
        }
        oprot.WriteFieldStop();
        oprot.WriteStructEnd();
      }
      finally
      {
        oprot.DecrementRecursionDepth();
      }
    }

    public override string ToString() {
      StringBuilder __sb = new StringBuilder("THCompanyProperties(");
      bool __first = true;
      if (EnforceSsoProvider != null && __isset.enforceSsoProvider) {
        if(!__first) { __sb.Append(", "); }
        __first = false;
        __sb.Append("EnforceSsoProvider: ");
        __sb.Append(EnforceSsoProvider);
      }
      if (__isset.disabled) {
        if(!__first) { __sb.Append(", "); }
        __first = false;
        __sb.Append("Disabled: ");
        __sb.Append(Disabled);
      }
      if (PaymentReauthLink != null && __isset.paymentReauthLink) {
        if(!__first) { __sb.Append(", "); }
        __first = false;
        __sb.Append("PaymentReauthLink: ");
        __sb.Append(PaymentReauthLink);
      }
      __sb.Append(")");
      return __sb.ToString();
    }

  }

}
#endif


text:
export interface Methods {
    GET: 'GET';
    POST: 'POST';
    PUT: 'PUT';
    DELETE: 'DELETE';
    PATCH: 'PATCH';
    OPTIONS: 'OPTIONS';
    HEAD: 'HEAD';
}
export declare const METHODS: Methods;
export interface Events {
    READY_STATE_CHANGE: 'readystatechange';
    LOAD_START: 'loadstart';
    PROGRESS: 'progress';
    ABORT: 'abort';
    ERROR: 'error';
    LOAD: 'load';
    TIMEOUT: 'timeout';
    LOAD_END: 'loadend';
}
export declare const EVENTS: {
    READY_STATE_CHANGE: string;
    LOAD_START: string;
    PROGRESS: string;
    ABORT: string;
    ERROR: string;
    LOAD: string;
    TIMEOUT: string;
    LOAD_END: string;
};


text:
package com.leilu.kingweather;

import android.app.Application;

public class MyApp extends Application {

}


text:
#include "coap_config.h"

#ifdef HAVE_STDIO_H
#  include <stdio.h>
#endif

#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
# define OPTVAL_T(t)         (t)
# define OPTVAL_GT(t)        (t)
#endif
#ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
# define OPTVAL_T(t)         (const char*)(t)
# define OPTVAL_GT(t)        (char*)(t)
# undef CMSG_DATA
# define CMSG_DATA WSA_CMSG_DATA
#endif
#ifdef HAVE_SYS_UIO_H
# include <sys/uio.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <errno.h>

#ifdef WITH_CONTIKI
# include "uip.h"
#endif

#include "libcoap.h"
#include "coap_debug.h"
#include "mem.h"
#include "net.h"
#include "coap_io.h"
#include "pdu.h"
#include "utlist.h"
#include "resource.h"

#if !defined(WITH_CONTIKI)
 /* define generic PKTINFO for IPv4 */
#if defined(IP_PKTINFO)
#  define GEN_IP_PKTINFO IP_PKTINFO
#elif defined(IP_RECVDSTADDR)
#  define GEN_IP_PKTINFO IP_RECVDSTADDR
#else
#  error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS."
#endif /* IP_PKTINFO */

/* define generic KTINFO for IPv6 */
#ifdef IPV6_RECVPKTINFO
#  define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO
#elif defined(IPV6_PKTINFO)
#  define GEN_IPV6_PKTINFO IPV6_PKTINFO
#else
#  error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS."
#endif /* IPV6_RECVPKTINFO */
#endif

void coap_free_endpoint(coap_endpoint_t *ep);

#ifdef WITH_CONTIKI
static int ep_initialized = 0;

struct coap_endpoint_t *
  coap_malloc_endpoint() {
  static struct coap_endpoint_t ep;

  if (ep_initialized) {
    return NULL;
  } else {
    ep_initialized = 1;
    return &ep;
  }
}

void
coap_mfree_endpoint(struct coap_endpoint_t *ep) {
  ep_initialized = 0;
  coap_session_mfree(&ep->hello);
}

int
coap_socket_bind_udp(coap_socket_t *sock,
  const coap_address_t *listen_addr,
  coap_address_t *bound_addr) {
  sock->conn = udp_new(NULL, 0, NULL);

  if (!sock->conn) {
    coap_log(LOG_WARNING, "coap_socket_bind_udp");
    return 0;
  }

  coap_address_init(bound_addr);
  uip_ipaddr_copy(&bound_addr->addr, &listen_addr->addr);
  bound_addr->port = listen_addr->port;
  udp_bind((struct uip_udp_conn *)sock->conn, bound_addr->port);
  return 1;
}

int
coap_socket_connect_udp(coap_socket_t *sock,
  const coap_address_t *local_if,
  const coap_address_t *server,
  int default_port,
  coap_address_t *local_addr,
  coap_address_t *remote_addr) {
  return 0;
}

int
coap_socket_connect_tcp1(coap_socket_t *sock,
                         const coap_address_t *local_if,
                         const coap_address_t *server,
                         int default_port,
                         coap_address_t *local_addr,
                         coap_address_t *remote_addr) {
  return 0;
}

int
coap_socket_connect_tcp2(coap_socket_t *sock,
                         coap_address_t *local_addr,
                         coap_address_t *remote_addr) {
  return 0;
}

int
coap_socket_bind_tcp(coap_socket_t *sock,
                     const coap_address_t *listen_addr,
                     coap_address_t *bound_addr) {
  return 0;
}

int
coap_socket_accept_tcp(coap_socket_t *server,
                        coap_socket_t *new_client,
                        coap_address_t *local_addr,
                        coap_address_t *remote_addr) {
  return 0;
}

ssize_t
coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) {
  return -1;
}

ssize_t
coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) {
  return -1;
}

void coap_socket_close(coap_socket_t *sock) {
  if (sock->conn)
    uip_udp_remove((struct uip_udp_conn *)sock->conn);
  sock->flags = COAP_SOCKET_EMPTY;
}

#else

static const char *coap_socket_format_errno( int error );

struct coap_endpoint_t *
  coap_malloc_endpoint(void) {
  return (struct coap_endpoint_t *)coap_malloc_type(COAP_ENDPOINT, sizeof(struct coap_endpoint_t));
}

void
coap_mfree_endpoint(struct coap_endpoint_t *ep) {
  coap_session_mfree(&ep->hello);
  coap_free_type(COAP_ENDPOINT, ep);
}

int
coap_socket_bind_udp(coap_socket_t *sock,
  const coap_address_t *listen_addr,
  coap_address_t *bound_addr) {
  int on = 1, off = 0;
#ifdef _WIN32
  u_long u_on = 1;
#endif

  sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_DGRAM, 0);

  if (sock->fd == COAP_INVALID_SOCKET) {
    coap_log(LOG_WARNING,
             "coap_socket_bind_udp: socket: %s\n", coap_socket_strerror());
    goto error;
  }

#ifdef _WIN32
  if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
#else
  if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
#endif
    coap_log(LOG_WARNING,
         "coap_socket_bind_udp: ioctl FIONBIO: %s\n", coap_socket_strerror());
  }

  if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
    coap_log(LOG_WARNING,
             "coap_socket_bind_udp: setsockopt SO_REUSEADDR: %s\n",
              coap_socket_strerror());

  switch (listen_addr->addr.sa.sa_family) {
  case AF_INET:
    if (setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
      coap_log(LOG_ALERT,
               "coap_socket_bind_udp: setsockopt IP_PKTINFO: %s\n",
                coap_socket_strerror());
    break;
  case AF_INET6:
    /* Configure the socket as dual-stacked */
    if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
      coap_log(LOG_ALERT,
               "coap_socket_bind_udp: setsockopt IPV6_V6ONLY: %s\n",
                coap_socket_strerror());
    if (setsockopt(sock->fd, IPPROTO_IPV6, GEN_IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
      coap_log(LOG_ALERT,
               "coap_socket_bind_udp: setsockopt IPV6_PKTINFO: %s\n",
                coap_socket_strerror());
    setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), sizeof(on)); /* ignore error, because the likely cause is that IPv4 is disabled at the os level */
    break;
  default:
    coap_log(LOG_ALERT, "coap_socket_bind_udp: unsupported sa_family\n");
    break;
  }

  if (bind(sock->fd, &listen_addr->addr.sa, listen_addr->size) == COAP_SOCKET_ERROR) {
    coap_log(LOG_WARNING, "coap_socket_bind_udp: bind: %s\n",
             coap_socket_strerror());
    goto error;
  }

  bound_addr->size = (socklen_t)sizeof(*bound_addr);
  if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) {
    coap_log(LOG_WARNING,
             "coap_socket_bind_udp: getsockname: %s\n",
              coap_socket_strerror());
    goto error;
  }

  return 1;

error:
  coap_socket_close(sock);
  return 0;
}

int
coap_socket_connect_tcp1(coap_socket_t *sock,
                         const coap_address_t *local_if,
                         const coap_address_t *server,
                         int default_port,
                         coap_address_t *local_addr,
                         coap_address_t *remote_addr) {
  int on = 1, off = 0;
#ifdef _WIN32
  u_long u_on = 1;
#endif
  coap_address_t connect_addr;
  coap_address_copy( &connect_addr, server );

  sock->flags &= ~COAP_SOCKET_CONNECTED;
  sock->fd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0);

  if (sock->fd == COAP_INVALID_SOCKET) {
    coap_log(LOG_WARNING,
             "coap_socket_connect_tcp1: socket: %s\n",
             coap_socket_strerror());
    goto error;
  }

#ifdef _WIN32
  if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
#else
  if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
#endif
    coap_log(LOG_WARNING,
             "coap_socket_connect_tcp1: ioctl FIONBIO: %s\n",
             coap_socket_strerror());
  }

  switch (server->addr.sa.sa_family) {
  case AF_INET:
    if (connect_addr.addr.sin.sin_port == 0)
      connect_addr.addr.sin.sin_port = htons(default_port);
    break;
  case AF_INET6:
    if (connect_addr.addr.sin6.sin6_port == 0)
      connect_addr.addr.sin6.sin6_port = htons(default_port);
    /* Configure the socket as dual-stacked */
    if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
      coap_log(LOG_WARNING,
               "coap_socket_connect_tcp1: setsockopt IPV6_V6ONLY: %s\n",
               coap_socket_strerror());
    break;
  default:
    coap_log(LOG_ALERT, "coap_socket_connect_tcp1: unsupported sa_family\n");
    break;
  }

  if (local_if && local_if->addr.sa.sa_family) {
    coap_address_copy(local_addr, local_if);
    if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
      coap_log(LOG_WARNING,
               "coap_socket_connect_tcp1: setsockopt SO_REUSEADDR: %s\n",
               coap_socket_strerror());
    if (bind(sock->fd, &local_if->addr.sa, local_if->size) == COAP_SOCKET_ERROR) {
      coap_log(LOG_WARNING, "coap_socket_connect_tcp1: bind: %s\n",
               coap_socket_strerror());
      goto error;
    }
  } else {
    local_addr->addr.sa.sa_family = server->addr.sa.sa_family;
  }

  if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) {
#ifdef _WIN32
    if (WSAGetLastError() == WSAEWOULDBLOCK) {
#else
    if (errno == EINPROGRESS) {
#endif
      /*
       * COAP_SOCKET_CONNECTED needs to be set here as there will be reads/writes
       * by underlying TLS libraries during connect() and we do not want to
       * assert() in coap_read_session() or coap_write_session() when called by coap_read()
       */
      sock->flags |= COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CONNECTED;
      return 1;
    }
    coap_log(LOG_WARNING, "coap_socket_connect_tcp1: connect: %s\n",
             coap_socket_strerror());
    goto error;
  }

  if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
    coap_log(LOG_WARNING, "coap_socket_connect_tcp1: getsockname: %s\n",
             coap_socket_strerror());
  }

  if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) {
    coap_log(LOG_WARNING, "coap_socket_connect_tcp1: getpeername: %s\n",
             coap_socket_strerror());
  }

  sock->flags |= COAP_SOCKET_CONNECTED;
  return 1;

error:
  coap_socket_close(sock);
  return 0;
}

int
coap_socket_connect_tcp2(coap_socket_t *sock,
                         coap_address_t *local_addr,
                         coap_address_t *remote_addr) {
  int error = 0;
#ifdef _WIN32
  int optlen = (int)sizeof( error );
#else
  socklen_t optlen = (socklen_t)sizeof( error );
#endif

  sock->flags &= ~(COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CAN_CONNECT);

  if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, OPTVAL_GT(&error),
    &optlen) == COAP_SOCKET_ERROR) {
    coap_log(LOG_WARNING, "coap_socket_finish_connect_tcp: getsockopt: %s\n",
      coap_socket_strerror());
  }

  if (error) {
    coap_log(LOG_WARNING,
             "coap_socket_finish_connect_tcp: connect failed: %s\n",
             coap_socket_format_errno(error));
    coap_socket_close(sock);
    return 0;
  }

  if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
    coap_log(LOG_WARNING, "coap_socket_connect_tcp: getsockname: %s\n",
             coap_socket_strerror());
  }

  if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) {
    coap_log(LOG_WARNING, "coap_socket_connect_tcp: getpeername: %s\n",
             coap_socket_strerror());
  }

  return 1;
}

int
coap_socket_bind_tcp(coap_socket_t *sock,
                     const coap_address_t *listen_addr,
                     coap_address_t *bound_addr) {
  int on = 1, off = 0;
#ifdef _WIN32
  u_long u_on = 1;
#endif

  sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_STREAM, 0);

  if (sock->fd == COAP_INVALID_SOCKET) {
    coap_log(LOG_WARNING, "coap_socket_bind_tcp: socket: %s\n",
             coap_socket_strerror());
    goto error;
  }

#ifdef _WIN32
  if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
#else
  if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
#endif
    coap_log(LOG_WARNING, "coap_socket_bind_tcp: ioctl FIONBIO: %s\n",
                           coap_socket_strerror());
  }
  if (setsockopt (sock->fd, SOL_SOCKET, SO_KEEPALIVE, OPTVAL_T(&on),
                  sizeof (on)) == COAP_SOCKET_ERROR)
    coap_log(LOG_WARNING,
             "coap_socket_bind_tcp: setsockopt SO_KEEPALIVE: %s\n",
             coap_socket_strerror());

  if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on),
                 sizeof(on)) == COAP_SOCKET_ERROR)
    coap_log(LOG_WARNING,
             "coap_socket_bind_tcp: setsockopt SO_REUSEADDR: %s\n",
             coap_socket_strerror());

  switch (listen_addr->addr.sa.sa_family) {
  case AF_INET:
    break;
  case AF_INET6:
    /* Configure the socket as dual-stacked */
    if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
      coap_log(LOG_ALERT,
               "coap_socket_bind_tcp: setsockopt IPV6_V6ONLY: %s\n",
               coap_socket_strerror());
    break;
  default:
    coap_log(LOG_ALERT, "coap_socket_bind_tcp: unsupported sa_family\n");
  }

  if (bind(sock->fd, &listen_addr->addr.sa, listen_addr->size) == COAP_SOCKET_ERROR) {
    coap_log(LOG_ALERT, "coap_socket_bind_tcp: bind: %s\n",
             coap_socket_strerror());
    goto error;
  }

  bound_addr->size = (socklen_t)sizeof(*bound_addr);
  if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) {
    coap_log(LOG_WARNING, "coap_socket_bind_tcp: getsockname: %s\n",
             coap_socket_strerror());
    goto error;
  }

  if (listen(sock->fd, 5) == COAP_SOCKET_ERROR) {
    coap_log(LOG_ALERT, "coap_socket_bind_tcp: listen: %s\n",
             coap_socket_strerror());
    goto  error;
  }

  return 1;

error:
  coap_socket_close(sock);
  return 0;
}

int
coap_socket_accept_tcp(coap_socket_t *server,
                       coap_socket_t *new_client,
                       coap_address_t *local_addr,
                       coap_address_t *remote_addr) {
#ifdef _WIN32
  u_long u_on = 1;
#else
  int on = 1;
#endif

  server->flags &= ~COAP_SOCKET_CAN_ACCEPT;

  new_client->fd = accept(server->fd, &remote_addr->addr.sa,
                          &remote_addr->size);
  if (new_client->fd == COAP_INVALID_SOCKET) {
    coap_log(LOG_WARNING, "coap_socket_accept_tcp: accept: %s\n",
             coap_socket_strerror());
    return 0;
  }

  if (getsockname( new_client->fd, &local_addr->addr.sa, &local_addr->size) < 0)
    coap_log(LOG_WARNING, "coap_socket_accept_tcp: getsockname: %s\n",
             coap_socket_strerror());

  #ifdef _WIN32
  if (ioctlsocket(new_client->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
#else
  if (ioctl(new_client->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
#endif
    coap_log(LOG_WARNING, "coap_socket_accept_tcp: ioctl FIONBIO: %s\n",
             coap_socket_strerror());
  }

  return 1;
}

int
coap_socket_connect_udp(coap_socket_t *sock,
  const coap_address_t *local_if,
  const coap_address_t *server,
  int default_port,
  coap_address_t *local_addr,
  coap_address_t *remote_addr) {
  int on = 1, off = 0;
#ifdef _WIN32
  u_long u_on = 1;
#endif
  coap_address_t connect_addr;
  int is_mcast = coap_is_mcast(server);
  coap_address_copy(&connect_addr, server);

  sock->flags &= ~(COAP_SOCKET_CONNECTED | COAP_SOCKET_MULTICAST);
  sock->fd = socket(connect_addr.addr.sa.sa_family, SOCK_DGRAM, 0);

  if (sock->fd == COAP_INVALID_SOCKET) {
    coap_log(LOG_WARNING, "coap_socket_connect_udp: socket: %s\n",
             coap_socket_strerror());
    goto error;
  }

#ifdef _WIN32
  if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
#else
  if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
#endif
    coap_log(LOG_WARNING, "coap_socket_connect_udp: ioctl FIONBIO: %s\n",
             coap_socket_strerror());
  }

  switch (connect_addr.addr.sa.sa_family) {
  case AF_INET:
    if (connect_addr.addr.sin.sin_port == 0)
      connect_addr.addr.sin.sin_port = htons(default_port);
    break;
  case AF_INET6:
    if (connect_addr.addr.sin6.sin6_port == 0)
      connect_addr.addr.sin6.sin6_port = htons(default_port);
    /* Configure the socket as dual-stacked */
    if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
      coap_log(LOG_WARNING,
               "coap_socket_connect_udp: setsockopt IPV6_V6ONLY: %s\n",
               coap_socket_strerror());
    break;
  default:
    coap_log(LOG_ALERT, "coap_socket_connect_udp: unsupported sa_family\n");
    break;
  }

  if (local_if && local_if->addr.sa.sa_family) {
    if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
      coap_log(LOG_WARNING,
               "coap_socket_connect_udp: setsockopt SO_REUSEADDR: %s\n",
               coap_socket_strerror());
    if (bind(sock->fd, &local_if->addr.sa, local_if->size) == COAP_SOCKET_ERROR) {
      coap_log(LOG_WARNING, "coap_socket_connect_udp: bind: %s\n",
               coap_socket_strerror());
      goto error;
    }
  }

  /* special treatment for sockets that are used for multicast communication */
  if (is_mcast) {
    if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
      coap_log(LOG_WARNING,
              "coap_socket_connect_udp: getsockname for multicast socket: %s\n",
              coap_socket_strerror());
    }
    coap_address_copy(remote_addr, &connect_addr);
    sock->flags |= COAP_SOCKET_MULTICAST;
    return 1;
  }

  if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) {
    coap_log(LOG_WARNING, "coap_socket_connect_udp: connect: %s\n",
             coap_socket_strerror());
    goto error;
  }

  if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
    coap_log(LOG_WARNING, "coap_socket_connect_udp: getsockname: %s\n",
             coap_socket_strerror());
  }

  if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) {
    coap_log(LOG_WARNING, "coap_socket_connect_udp: getpeername: %s\n",
             coap_socket_strerror());
  }

  sock->flags |= COAP_SOCKET_CONNECTED;
  return 1;

error:
  coap_socket_close(sock);
  return 0;
}

void coap_socket_close(coap_socket_t *sock) {
  if (sock->fd != COAP_INVALID_SOCKET) {
    coap_closesocket(sock->fd);
    sock->fd = COAP_INVALID_SOCKET;
  }
  sock->flags = COAP_SOCKET_EMPTY;
}

ssize_t
coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) {
  ssize_t r;

  sock->flags &= ~(COAP_SOCKET_WANT_WRITE | COAP_SOCKET_CAN_WRITE);
#ifdef _WIN32
  r = send(sock->fd, (const char *)data, (int)data_len, 0);
#else
  r = send(sock->fd, data, data_len, 0);
#endif
  if (r == COAP_SOCKET_ERROR) {
#ifdef _WIN32
    if (WSAGetLastError() == WSAEWOULDBLOCK) {
#elif EAGAIN != EWOULDBLOCK
    if (errno==EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
#else
    if (errno==EAGAIN || errno == EINTR) {
#endif
      sock->flags |= COAP_SOCKET_WANT_WRITE;
      return 0;
    }
    coap_log(LOG_WARNING, "coap_socket_write: send: %s\n",
             coap_socket_strerror());
    return -1;
  }
  if (r < (ssize_t)data_len)
    sock->flags |= COAP_SOCKET_WANT_WRITE;
  return r;
}

ssize_t
coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) {
  ssize_t r;
#ifdef _WIN32
  int error;
#endif

#ifdef _WIN32
  r = recv(sock->fd, (char *)data, (int)data_len, 0);
#else
  r = recv(sock->fd, data, data_len, 0);
#endif
  if (r == 0) {
    /* graceful shutdown */
    sock->flags &= ~COAP_SOCKET_CAN_READ;
    return -1;
  } else if (r == COAP_SOCKET_ERROR) {
    sock->flags &= ~COAP_SOCKET_CAN_READ;
#ifdef _WIN32
    error = WSAGetLastError();
    if (error == WSAEWOULDBLOCK) {
#elif EAGAIN != EWOULDBLOCK
    if (errno==EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
#else
    if (errno==EAGAIN || errno == EINTR) {
#endif
      return 0;
    }
#ifdef _WIN32
    if (error != WSAECONNRESET)
#else
    if (errno != ECONNRESET)
#endif
      coap_log(LOG_WARNING, "coap_socket_read: recv: %s\n",
               coap_socket_strerror());
    return -1;
  }
  if (r < (ssize_t)data_len)
    sock->flags &= ~COAP_SOCKET_CAN_READ;
  return r;
}

#endif  /* WITH_CONTIKI */

#if (!defined(WITH_CONTIKI)) != ( defined(HAVE_NETINET_IN_H) || defined(HAVE_WS2TCPIP_H) )
/* define struct in6_pktinfo and struct in_pktinfo if not available
   FIXME: check with configure
*/
struct in6_pktinfo {
  struct in6_addr ipi6_addr;        /* src/dst IPv6 address */
  unsigned int ipi6_ifindex;        /* send/recv interface index */
};

struct in_pktinfo {
  int ipi_ifindex;
  struct in_addr ipi_spec_dst;
  struct in_addr ipi_addr;
};
#endif

#if !defined(WITH_CONTIKI) && !defined(SOL_IP)
/* Solaris expects level IPPROTO_IP for ancillary data. */
#define SOL_IP IPPROTO_IP
#endif

#ifdef __GNUC__
#define UNUSED_PARAM __attribute__ ((unused))
#else /* not a GCC */
#define UNUSED_PARAM
#endif /* GCC */

#if defined(_WIN32)
#include <mswsock.h>
static __declspec(thread) LPFN_WSARECVMSG lpWSARecvMsg = NULL;
/* Map struct WSABUF fields to their posix counterpart */
#define msghdr _WSAMSG
#define msg_name name
#define msg_namelen namelen
#define msg_iov lpBuffers
#define msg_iovlen dwBufferCount
#define msg_control Control.buf
#define msg_controllen Control.len
#define iovec _WSABUF
#define iov_base buf
#define iov_len len
#define iov_len_t u_long
#undef CMSG_DATA
#define CMSG_DATA WSA_CMSG_DATA
#define ipi_spec_dst ipi_addr
#else
#define iov_len_t size_t
#endif

ssize_t
coap_network_send(coap_socket_t *sock, const coap_session_t *session, const uint8_t *data, size_t datalen) {
  ssize_t bytes_written = 0;

  if (!coap_debug_send_packet()) {
    bytes_written = (ssize_t)datalen;
#ifndef WITH_CONTIKI
  } else if (sock->flags & COAP_SOCKET_CONNECTED) {
#ifdef _WIN32
    bytes_written = send(sock->fd, (const char *)data, (int)datalen, 0);
#else
    bytes_written = send(sock->fd, data, datalen, 0);
#endif
#endif
  } else {
#ifndef WITH_CONTIKI
#ifdef _WIN32
    DWORD dwNumberOfBytesSent = 0;
    int r;
#endif
#ifndef COAP_BAD_RECVMSG
    /* a buffer large enough to hold all packet info types, ipv6 is the largest */
    char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
    struct msghdr mhdr;
    struct iovec iov[1];
    const void *addr = &session->remote_addr.addr;

    assert(session);

    memcpy (&iov[0].iov_base, &data, sizeof (iov[0].iov_base));
    iov[0].iov_len = (iov_len_t)datalen;

    memset(buf, 0, sizeof (buf));

    memset(&mhdr, 0, sizeof(struct msghdr));
    memcpy (&mhdr.msg_name, &addr, sizeof (mhdr.msg_name));
    mhdr.msg_namelen = session->remote_addr.size;

    mhdr.msg_iov = iov;
    mhdr.msg_iovlen = 1;

    if (!coap_address_isany(&session->local_addr) && !coap_is_mcast(&session->local_addr)) switch (session->local_addr.addr.sa.sa_family) {
    case AF_INET6:
    {
      struct cmsghdr *cmsg;

      if (IN6_IS_ADDR_V4MAPPED(&session->local_addr.addr.sin6.sin6_addr)) {
#if defined(IP_PKTINFO)
        struct in_pktinfo *pktinfo;
        mhdr.msg_control = buf;
        mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));

        cmsg = CMSG_FIRSTHDR(&mhdr);
        cmsg->cmsg_level = SOL_IP;
        cmsg->cmsg_type = IP_PKTINFO;
        cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));

        pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);

        pktinfo->ipi_ifindex = session->ifindex;
        memcpy(&pktinfo->ipi_spec_dst, session->local_addr.addr.sin6.sin6_addr.s6_addr + 12, sizeof(pktinfo->ipi_spec_dst));
#elif defined(IP_SENDSRCADDR)
        mhdr.msg_control = buf;
        mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));

        cmsg = CMSG_FIRSTHDR(&mhdr);
        cmsg->cmsg_level = IPPROTO_IP;
        cmsg->cmsg_type = IP_SENDSRCADDR;
        cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));

        memcpy(CMSG_DATA(cmsg), session->local_addr.addr.sin6.sin6_addr.s6_addr + 12, sizeof(struct in_addr));
#endif /* IP_PKTINFO */
      } else {
        struct in6_pktinfo *pktinfo;
        mhdr.msg_control = buf;
        mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));

        cmsg = CMSG_FIRSTHDR(&mhdr);
        cmsg->cmsg_level = IPPROTO_IPV6;
        cmsg->cmsg_type = IPV6_PKTINFO;
        cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));

        pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);

        pktinfo->ipi6_ifindex = session->ifindex;
        memcpy(&pktinfo->ipi6_addr, &session->local_addr.addr.sin6.sin6_addr, sizeof(pktinfo->ipi6_addr));
      }
      break;
    }
    case AF_INET:
    {
#if defined(IP_PKTINFO)
      struct cmsghdr *cmsg;
      struct in_pktinfo *pktinfo;

      mhdr.msg_control = buf;
      mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));

      cmsg = CMSG_FIRSTHDR(&mhdr);
      cmsg->cmsg_level = SOL_IP;
      cmsg->cmsg_type = IP_PKTINFO;
      cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));

      pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);

      pktinfo->ipi_ifindex = session->ifindex;
      memcpy(&pktinfo->ipi_spec_dst, &session->local_addr.addr.sin.sin_addr, sizeof(pktinfo->ipi_spec_dst));
#elif defined(IP_SENDSRCADDR)
      struct cmsghdr *cmsg;
      mhdr.msg_control = buf;
      mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));

      cmsg = CMSG_FIRSTHDR(&mhdr);
      cmsg->cmsg_level = IPPROTO_IP;
      cmsg->cmsg_type = IP_SENDSRCADDR;
      cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));

      memcpy(CMSG_DATA(cmsg), &session->local_addr.addr.sin.sin_addr, sizeof(struct in_addr));
#endif /* IP_PKTINFO */
      break;
    }
    default:
      /* error */
      coap_log(LOG_WARNING, "protocol not supported\n");
      bytes_written = -1;
    }
#endif /* ! COAP_BAD_RECVMSG */

#ifdef _WIN32
    r = WSASendMsg(sock->fd, &mhdr, 0 /*dwFlags*/, &dwNumberOfBytesSent, NULL /*lpOverlapped*/, NULL /*lpCompletionRoutine*/);
    if (r == 0)
      bytes_written = (ssize_t)dwNumberOfBytesSent;
    else
      bytes_written = -1;
#else
#ifndef COAP_BAD_RECVMSG
    bytes_written = sendmsg(sock->fd, &mhdr, 0);
#else /* COAP_BAD_RECVMSG */
    bytes_written = sendto(sock->fd, data, datalen, 0, &session->remote_addr.addr.sa, session->remote_addr.size);
#endif /* COAP_BAD_RECVMSG */
#endif
#else /* WITH_CONTIKI */
    /* FIXME: untested */
    /* FIXME: is there a way to check if send was successful? */
    (void)datalen;
    (void)data;
    uip_udp_packet_sendto((struct uip_udp_conn *)sock->conn, data, datalen,
      &session->remote_addr.addr, session->remote_addr.port);
    bytes_written = datalen;
#endif /* WITH_CONTIKI */
  }

  if (bytes_written < 0)
    coap_log(LOG_CRIT, "coap_network_send: %s\n", coap_socket_strerror());

  return bytes_written;
}

#define SIN6(A) ((struct sockaddr_in6 *)(A))

void
coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) {
  *address = packet->payload;
  *length = packet->length;
}

void coap_packet_set_addr(coap_packet_t *packet, const coap_address_t *src, const coap_address_t *dst) {
  coap_address_copy(&packet->src, src);
  coap_address_copy(&packet->dst, dst);
}

ssize_t
coap_network_read(coap_socket_t *sock, coap_packet_t *packet) {
  ssize_t len = -1;

  assert(sock);
  assert(packet);

  if ((sock->flags & COAP_SOCKET_CAN_READ) == 0) {
    return -1;
  } else {
    /* clear has-data flag */
    sock->flags &= ~COAP_SOCKET_CAN_READ;
  }

#ifndef WITH_CONTIKI
  if (sock->flags & COAP_SOCKET_CONNECTED) {
#ifdef _WIN32
    len = recv(sock->fd, (char *)packet->payload, COAP_RXBUFFER_SIZE, 0);
#else
    len = recv(sock->fd, packet->payload, COAP_RXBUFFER_SIZE, 0);
#endif
    if (len < 0) {
#ifdef _WIN32
      if (WSAGetLastError() == WSAECONNRESET) {
#else
      if (errno == ECONNREFUSED) {
#endif
        /* client-side ICMP destination unreachable, ignore it */
        coap_log(LOG_WARNING, "coap_network_read: unreachable\n");
        return -2;
      }
      coap_log(LOG_WARNING, "coap_network_read: %s\n", coap_socket_strerror());
      goto error;
    } else if (len > 0) {
      packet->length = (size_t)len;
    }
  } else {
#endif /* WITH_CONTIKI */
#if defined(_WIN32)
    DWORD dwNumberOfBytesRecvd = 0;
    int r;
#endif
#if !defined(WITH_CONTIKI)
#ifndef COAP_BAD_RECVMSG
    /* a buffer large enough to hold all packet info types, ipv6 is the largest */
    char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
    struct msghdr mhdr;
    struct iovec iov[1];

    iov[0].iov_base = packet->payload;
    iov[0].iov_len = (iov_len_t)COAP_RXBUFFER_SIZE;

    memset(&mhdr, 0, sizeof(struct msghdr));

    mhdr.msg_name = (struct sockaddr*)&packet->src.addr;
    mhdr.msg_namelen = sizeof(packet->src.addr);

    mhdr.msg_iov = iov;
    mhdr.msg_iovlen = 1;

    mhdr.msg_control = buf;
    mhdr.msg_controllen = sizeof(buf);

#if defined(_WIN32)
    if (!lpWSARecvMsg) {
      GUID wsaid = WSAID_WSARECVMSG;
      DWORD cbBytesReturned = 0;
      if (WSAIoctl(sock->fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaid, sizeof(wsaid), &lpWSARecvMsg, sizeof(lpWSARecvMsg), &cbBytesReturned, NULL, NULL) != 0) {
        coap_log(LOG_WARNING, "coap_network_read: no WSARecvMsg\n");
        return -1;
      }
    }
    r = lpWSARecvMsg(sock->fd, &mhdr, &dwNumberOfBytesRecvd, NULL /* LPWSAOVERLAPPED */, NULL /* LPWSAOVERLAPPED_COMPLETION_ROUTINE */);
    if (r == 0)
      len = (ssize_t)dwNumberOfBytesRecvd;
#else
    len = recvmsg(sock->fd, &mhdr, 0);
#endif

#else /* COAP_BAD_RECVMSG */
    packet->src.size = packet->src.size;
    len = recvfrom(sock->fd, packet->payload, COAP_RXBUFFER_SIZE, 0, &packet->src.addr.sa, &packet->src.size);
#endif /* COAP_BAD_RECVMSG */

    if (len < 0) {
#ifdef _WIN32
      if (WSAGetLastError() == WSAECONNRESET) {
#else
      if (errno == ECONNREFUSED) {
#endif
        /* server-side ICMP destination unreachable, ignore it. The destination address is in msg_name. */
        return 0;
      }
      coap_log(LOG_WARNING, "coap_network_read: %s\n", coap_socket_strerror());
      goto error;
    } else {
#ifndef COAP_BAD_RECVMSG
      struct cmsghdr *cmsg;

      packet->src.size = mhdr.msg_namelen;
      packet->length = (size_t)len;

      /* Walk through ancillary data records until the local interface
       * is found where the data was received. */
      for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) {

        /* get the local interface for IPv6 */
        if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
          union {
            uint8_t *c;
            struct in6_pktinfo *p;
          } u;
          u.c = CMSG_DATA(cmsg);
          packet->ifindex = (int)(u.p->ipi6_ifindex);
          memcpy(&packet->dst.addr.sin6.sin6_addr, &u.p->ipi6_addr, sizeof(struct in6_addr));
          break;
        }

        /* local interface for IPv4 */
#if defined(IP_PKTINFO)
        if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) {
          union {
            uint8_t *c;
            struct in_pktinfo *p;
          } u;
          u.c = CMSG_DATA(cmsg);
          packet->ifindex = u.p->ipi_ifindex;
          if (packet->dst.addr.sa.sa_family == AF_INET6) {
            memset(packet->dst.addr.sin6.sin6_addr.s6_addr, 0, 10);
            packet->dst.addr.sin6.sin6_addr.s6_addr[10] = 0xff;
            packet->dst.addr.sin6.sin6_addr.s6_addr[11] = 0xff;
            memcpy(packet->dst.addr.sin6.sin6_addr.s6_addr + 12, &u.p->ipi_addr, sizeof(struct in_addr));
          } else {
            memcpy(&packet->dst.addr.sin.sin_addr, &u.p->ipi_addr, sizeof(struct in_addr));
          }
          break;
        }
#elif defined(IP_RECVDSTADDR)
        if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
          packet->ifindex = 0;
          memcpy(&packet->dst.addr.sin.sin_addr, CMSG_DATA(cmsg), sizeof(struct in_addr));
          break;
        }
#endif /* IP_PKTINFO */
      }
#else /* COAP_BAD_RECVMSG */
      packet->length = (size_t)len;
      packet->ifindex = 0;
      if (getsockname(sock->fd, &packet->dst.addr.sa, &packet->dst.size) < 0) {
         coap_log(LOG_DEBUG, "Cannot determine local port\n");
         goto error;
      }
#endif /* COAP_BAD_RECVMSG */
    }
#endif /* !defined(WITH_CONTIKI) */
#ifdef WITH_CONTIKI
    /* FIXME: untested, make this work */
#define UIP_IP_BUF   ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
#define UIP_UDP_BUF  ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])

    if (uip_newdata()) {
      uip_ipaddr_copy(&packet->src.addr, &UIP_IP_BUF->srcipaddr);
      packet->src.port = UIP_UDP_BUF->srcport;
      uip_ipaddr_copy(&(packet)->dst.addr, &UIP_IP_BUF->destipaddr);
      packet->dst.port = UIP_UDP_BUF->destport;

      len = uip_datalen();

      if (len > COAP_RXBUFFER_SIZE) {
        /* FIXME: we might want to send back a response */
        coap_log(LOG_WARNING, "discarded oversized packet\n");
        return -1;
      }

      ((char *)uip_appdata)[len] = 0;
#ifndef NDEBUG
      if (LOG_DEBUG <= coap_get_log_level()) {
#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 40
#endif
        unsigned char addr_str[INET6_ADDRSTRLEN + 8];

        if (coap_print_addr(&packet->src, addr_str, INET6_ADDRSTRLEN + 8)) {
          coap_log(LOG_DEBUG, "received %zd bytes from %s\n", len, addr_str);
        }
      }
#endif /* NDEBUG */

      packet->length = len;
      memcpy(&packet->payload, uip_appdata, len);
    }

#undef UIP_IP_BUF
#undef UIP_UDP_BUF
#endif /* WITH_CONTIKI */
#ifndef WITH_CONTIKI
  }
#endif /* WITH_CONTIKI */

  if (len >= 0)
    return len;
#if !defined(WITH_CONTIKI)
error:
#endif
  return -1;
}

#if !defined(WITH_CONTIKI)

unsigned int
coap_write(coap_context_t *ctx,
           coap_socket_t *sockets[],
           unsigned int max_sockets,
           unsigned int *num_sockets,
           coap_tick_t now)
{
  coap_queue_t *nextpdu;
  coap_endpoint_t *ep;
  coap_session_t *s;
  coap_tick_t session_timeout;
  coap_tick_t timeout = 0;
  coap_session_t *tmp;

  *num_sockets = 0;

  /* Check to see if we need to send off any Observe requests */
  coap_check_notify(ctx);

  if (ctx->session_timeout > 0)
    session_timeout = ctx->session_timeout * COAP_TICKS_PER_SECOND;
  else
    session_timeout = COAP_DEFAULT_SESSION_TIMEOUT * COAP_TICKS_PER_SECOND;

  LL_FOREACH(ctx->endpoint, ep) {
    if (ep->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE | COAP_SOCKET_WANT_ACCEPT)) {
      if (*num_sockets < max_sockets)
        sockets[(*num_sockets)++] = &ep->sock;
    }
    LL_FOREACH_SAFE(ep->sessions, s, tmp) {
      if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 &&
          s->delayqueue == NULL &&
          (s->last_rx_tx + session_timeout <= now ||
           s->state == COAP_SESSION_STATE_NONE)) {
        coap_session_free(s);
      } else {
        if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 && s->delayqueue == NULL) {
          coap_tick_t s_timeout = (s->last_rx_tx + session_timeout) - now;
          if (timeout == 0 || s_timeout < timeout)
            timeout = s_timeout;
        }
        if (s->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE)) {
          if (*num_sockets < max_sockets)
            sockets[(*num_sockets)++] = &s->sock;
        }
      }
    }
  }
  LL_FOREACH_SAFE(ctx->sessions, s, tmp) {
    if (
        s->type == COAP_SESSION_TYPE_CLIENT
     && COAP_PROTO_RELIABLE(s->proto)
     && s->state == COAP_SESSION_STATE_ESTABLISHED
     && ctx->ping_timeout > 0
    ) {
      coap_tick_t s_timeout;
      if (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND <= now) {
        if ((s->last_ping > 0 && s->last_pong < s->last_ping)
          || coap_session_send_ping(s) == COAP_INVALID_TID)
        {
          /* Make sure the session object is not deleted in the callback */
          coap_session_reference(s);
          coap_session_disconnected(s, COAP_NACK_NOT_DELIVERABLE);
          coap_session_release(s);
          continue;
        }
        s->last_rx_tx = now;
        s->last_ping = now;
      }
      s_timeout = (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND) - now;
      if (timeout == 0 || s_timeout < timeout)
        timeout = s_timeout;
    }

    if (
        s->type == COAP_SESSION_TYPE_CLIENT
     && COAP_PROTO_RELIABLE(s->proto)
     && s->state == COAP_SESSION_STATE_CSM
     && ctx->csm_timeout > 0
    ) {
      coap_tick_t s_timeout;
      if (s->csm_tx == 0) {
        s->csm_tx = now;
      } else if (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND <= now) {
        /* Make sure the session object is not deleted in the callback */
        coap_session_reference(s);
        coap_session_disconnected(s, COAP_NACK_NOT_DELIVERABLE);
        coap_session_release(s);
        continue;
      }
      s_timeout = (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND) - now;
      if (timeout == 0 || s_timeout < timeout)
        timeout = s_timeout;
    }

    if (s->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE | COAP_SOCKET_WANT_CONNECT)) {
      if (*num_sockets < max_sockets)
        sockets[(*num_sockets)++] = &s->sock;
    }
  }

  nextpdu = coap_peek_next(ctx);

  while (nextpdu && now >= ctx->sendqueue_basetime && nextpdu->t <= now - ctx->sendqueue_basetime) {
    coap_retransmit(ctx, coap_pop_next(ctx));
    nextpdu = coap_peek_next(ctx);
  }

  if (nextpdu && (timeout == 0 || nextpdu->t - ( now - ctx->sendqueue_basetime ) < timeout))
    timeout = nextpdu->t - (now - ctx->sendqueue_basetime);

  if (ctx->dtls_context) {
    if (coap_dtls_is_context_timeout()) {
      coap_tick_t tls_timeout = coap_dtls_get_context_timeout(ctx->dtls_context);
      if (tls_timeout > 0) {
        if (tls_timeout < now + COAP_TICKS_PER_SECOND / 10)
          tls_timeout = now + COAP_TICKS_PER_SECOND / 10;
        coap_log(LOG_DEBUG, "** DTLS global timeout set to %dms\n",
                 (int)((tls_timeout - now) * 1000 / COAP_TICKS_PER_SECOND));
        if (timeout == 0 || tls_timeout - now < timeout)
          timeout = tls_timeout - now;
      }
    } else {
      LL_FOREACH(ctx->endpoint, ep) {
        if (ep->proto == COAP_PROTO_DTLS) {
          LL_FOREACH(ep->sessions, s) {
            if (s->proto == COAP_PROTO_DTLS && s->tls) {
              coap_tick_t tls_timeout = coap_dtls_get_timeout(s);
              while (tls_timeout > 0 && tls_timeout <= now) {
                coap_log(LOG_DEBUG, "** %s: DTLS retransmit timeout\n",
                         coap_session_str(s));
                coap_dtls_handle_timeout(s);
                if (s->tls)
                  tls_timeout = coap_dtls_get_timeout(s);
                else {
                  tls_timeout = 0;
                  timeout = 1;
                }
              }
              if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout))
                timeout = tls_timeout - now;
            }
          }
        }
      }
      LL_FOREACH(ctx->sessions, s) {
        if (s->proto == COAP_PROTO_DTLS && s->tls) {
          coap_tick_t tls_timeout = coap_dtls_get_timeout(s);
          while (tls_timeout > 0 && tls_timeout <= now) {
            coap_log(LOG_DEBUG, "** %s: DTLS retransmit timeout\n", coap_session_str(s));
            coap_dtls_handle_timeout(s);
            if (s->tls)
              tls_timeout = coap_dtls_get_timeout(s);
            else {
              tls_timeout = 0;
              timeout = 1;
            }
          }
          if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout))
            timeout = tls_timeout - now;
        }
      }
    }
  }

  return (unsigned int)((timeout * 1000 + COAP_TICKS_PER_SECOND - 1) / COAP_TICKS_PER_SECOND);
}

int
coap_run_once(coap_context_t *ctx, unsigned timeout_ms) {
  fd_set readfds, writefds, exceptfds;
  coap_fd_t nfds = 0;
  struct timeval tv;
  coap_tick_t before, now;
  int result;
  coap_socket_t *sockets[64];
  unsigned int num_sockets = 0, i, timeout;

  coap_ticks(&before);

  timeout = coap_write(ctx, sockets, (unsigned int)(sizeof(sockets) / sizeof(sockets[0])), &num_sockets, before);
  if (timeout == 0 || timeout_ms < timeout)
    timeout = timeout_ms;

  FD_ZERO(&readfds);
  FD_ZERO(&writefds);
  FD_ZERO(&exceptfds);
  for (i = 0; i < num_sockets; i++) {
    if (sockets[i]->fd + 1 > nfds)
      nfds = sockets[i]->fd + 1;
    if (sockets[i]->flags & COAP_SOCKET_WANT_READ)
      FD_SET(sockets[i]->fd, &readfds);
    if (sockets[i]->flags & COAP_SOCKET_WANT_WRITE)
      FD_SET(sockets[i]->fd, &writefds);
    if (sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT)
      FD_SET(sockets[i]->fd, &readfds);
    if (sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) {
      FD_SET(sockets[i]->fd, &writefds);
      FD_SET(sockets[i]->fd, &exceptfds);
    }
  }

  if ( timeout > 0 ) {
    tv.tv_usec = (timeout % 1000) * 1000;
    tv.tv_sec = (long)(timeout / 1000);
  }

  result = select(nfds, &readfds, &writefds, &exceptfds, timeout > 0 ? &tv : NULL);

  if (result < 0) {   /* error */
#ifdef _WIN32
    if (WSAGetLastError() != WSAEINVAL) { /* May happen because of ICMP */
#else
    if (errno != EINTR) {
#endif
      coap_log(LOG_DEBUG, "%s", coap_socket_strerror());
      return -1;
    }
  }

  if (result > 0) {
    for (i = 0; i < num_sockets; i++) {
      if ((sockets[i]->flags & COAP_SOCKET_WANT_READ) && FD_ISSET(sockets[i]->fd, &readfds))
        sockets[i]->flags |= COAP_SOCKET_CAN_READ;
      if ((sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) && FD_ISSET(sockets[i]->fd, &readfds))
        sockets[i]->flags |= COAP_SOCKET_CAN_ACCEPT;
      if ((sockets[i]->flags & COAP_SOCKET_WANT_WRITE) && FD_ISSET(sockets[i]->fd, &writefds))
        sockets[i]->flags |= COAP_SOCKET_CAN_WRITE;
      if ((sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) && (FD_ISSET(sockets[i]->fd, &writefds) || FD_ISSET(sockets[i]->fd, &exceptfds)))
        sockets[i]->flags |= COAP_SOCKET_CAN_CONNECT;
    }
  }

  coap_ticks(&now);
  coap_read(ctx, now);

  return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND);
}

#else
int coap_run_once(coap_context_t *ctx, unsigned int timeout_ms) {
  return -1;
}

unsigned int
coap_write(coap_context_t *ctx,
           coap_socket_t *sockets[],
           unsigned int max_sockets,
           unsigned int *num_sockets,
           coap_tick_t now)
{
  *num_sockets = 0;
  return 0;
}
#endif

#ifdef _WIN32
static const char *coap_socket_format_errno(int error) {
  static char szError[256];
  if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)szError, (DWORD)sizeof(szError), NULL) == 0)
    strcpy(szError, "Unknown error");
  return szError;
}

const char *coap_socket_strerror(void) {
  return coap_socket_format_errno(WSAGetLastError());
}
#else
#ifndef WITH_CONTIKI
static const char *coap_socket_format_errno(int error) {
  return strerror(error);
}
#endif /* WITH_CONTIKI */

const char *coap_socket_strerror(void) {
  return strerror(errno);
}
#endif

ssize_t
coap_socket_send(coap_socket_t *sock, coap_session_t *session,
  const uint8_t *data, size_t data_len) {
  return session->context->network_send(sock, session, data, data_len);
}

#undef SIN6


text:
module Resque
  module Stress
    class Sampler
      attr_reader :harness, :injector
      attr_accessor :stat_handler, :sample_rate

      def initialize(harness, injector, sample_rate)
        @harness = harness
        @injector = injector
        @sample_rate = sample_rate
      end

      def current_stats
        [harness.target_rate, injector.current_rate, injector.total_injections]
      end

      def stat_handler=(callable)
        @stat_handler = callable
      end

      def run
        while(true) do
          sleep(sample_rate.to_f)
          stat_handler.call(*current_stats)
        end
      end
    end
  end
end