|
Java example source code file (attachListener_bsd.cpp)
The attachListener_bsd.cpp Java example source code/* * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #include "precompiled.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/os.hpp" #include "services/attachListener.hpp" #include "services/dtraceAttacher.hpp" #include <unistd.h> #include <signal.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/stat.h> #ifndef UNIX_PATH_MAX #define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)0)->sun_path) #endif // The attach mechanism on Bsd uses a UNIX domain socket. An attach listener // thread is created at startup or is created on-demand via a signal from // the client tool. The attach listener creates a socket and binds it to a file // in the filesystem. The attach listener then acts as a simple (single- // threaded) server - it waits for a client to connect, reads the request, // executes it, and returns the response to the client via the socket // connection. // // As the socket is a UNIX domain socket it means that only clients on the // local machine can connect. In addition there are two other aspects to // the security: // 1. The well known file that the socket is bound to has permission 400 // 2. When a client connect, the SO_PEERCRED socket option is used to // obtain the credentials of client. We check that the effective uid // of the client matches this process. // forward reference class BsdAttachOperation; class BsdAttachListener: AllStatic { private: // the path to which we bind the UNIX domain socket static char _path[UNIX_PATH_MAX]; static bool _has_path; // the file descriptor for the listening socket static int _listener; static void set_path(char* path) { if (path == NULL) { _has_path = false; } else { strncpy(_path, path, UNIX_PATH_MAX); _path[UNIX_PATH_MAX-1] = '\0'; _has_path = true; } } static void set_listener(int s) { _listener = s; } // reads a request from the given connected socket static BsdAttachOperation* read_request(int s); public: enum { ATTACH_PROTOCOL_VER = 1 // protocol version }; enum { ATTACH_ERROR_BADVERSION = 101 // error codes }; // initialize the listener, returns 0 if okay static int init(); static char* path() { return _path; } static bool has_path() { return _has_path; } static int listener() { return _listener; } // write the given buffer to a socket static int write_fully(int s, char* buf, int len); static BsdAttachOperation* dequeue(); }; class BsdAttachOperation: public AttachOperation { private: // the connection to the client int _socket; public: void complete(jint res, bufferedStream* st); void set_socket(int s) { _socket = s; } int socket() const { return _socket; } BsdAttachOperation(char* name) : AttachOperation(name) { set_socket(-1); } }; // statics char BsdAttachListener::_path[UNIX_PATH_MAX]; bool BsdAttachListener::_has_path; int BsdAttachListener::_listener = -1; // Supporting class to help split a buffer into individual components class ArgumentIterator : public StackObj { private: char* _pos; char* _end; public: ArgumentIterator(char* arg_buffer, size_t arg_size) { _pos = arg_buffer; _end = _pos + arg_size - 1; } char* next() { if (*_pos == '\0') { return NULL; } char* res = _pos; char* next_pos = strchr(_pos, '\0'); if (next_pos < _end) { next_pos++; } _pos = next_pos; return res; } }; // atexit hook to stop listener and unlink the file that it is // bound too. extern "C" { static void listener_cleanup() { static int cleanup_done; if (!cleanup_done) { cleanup_done = 1; int s = BsdAttachListener::listener(); if (s != -1) { ::close(s); } if (BsdAttachListener::has_path()) { ::unlink(BsdAttachListener::path()); } } } } // Initialization - create a listener socket and bind it to a file int BsdAttachListener::init() { char path[UNIX_PATH_MAX]; // socket file char initial_path[UNIX_PATH_MAX]; // socket file during setup int listener; // listener socket (file descriptor) // register function to cleanup ::atexit(listener_cleanup); int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d", os::get_temp_directory(), os::current_process_id()); if (n < (int)UNIX_PATH_MAX) { n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path); } if (n >= (int)UNIX_PATH_MAX) { return -1; } // create the listener socket listener = ::socket(PF_UNIX, SOCK_STREAM, 0); if (listener == -1) { return -1; } // bind socket struct sockaddr_un addr; addr.sun_family = AF_UNIX; strcpy(addr.sun_path, initial_path); ::unlink(initial_path); int res = ::bind(listener, (struct sockaddr*)&addr, sizeof(addr)); if (res == -1) { ::close(listener); return -1; } // put in listen mode, set permissions, and rename into place res = ::listen(listener, 5); if (res == 0) { RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res); if (res == 0) { // make sure the file is owned by the effective user and effective group // (this is the default on linux, but not on mac os) RESTARTABLE(::chown(initial_path, geteuid(), getegid()), res); if (res == 0) { res = ::rename(initial_path, path); } } } if (res == -1) { ::close(listener); ::unlink(initial_path); return -1; } set_path(path); set_listener(listener); return 0; } // Given a socket that is connected to a peer we read the request and // create an AttachOperation. As the socket is blocking there is potential // for a denial-of-service if the peer does not response. However this happens // after the peer credentials have been checked and in the worst case it just // means that the attach listener thread is blocked. // BsdAttachOperation* BsdAttachListener::read_request(int s) { char ver_str[8]; sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER); // The request is a sequence of strings so we first figure out the // expected count and the maximum possible length of the request. // The request is: // <ver>0 Other Java examples (source code examples)Here is a short list of links related to this Java attachListener_bsd.cpp source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.